Exemple #1
0
def get_module_sizes(module, *args, **kwargs):
    rtlil_text = rtlil.convert(module, *args, **kwargs)

    script = """
        read_ilang <<rtlil
        {}
        rtlil
        
        expose top
        
        synth_xilinx -abc9
    """.format(rtlil_text)

    popen = subprocess.Popen(["yosys", "-s", "-"],
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             encoding="utf-8")
    output, error = popen.communicate(script)

    return {
        re.findall("== (.*?) ===", section)[0]:
        re.findall("Estimated number of LCs:\\W*(\\d+)", section)[0]
        for section in re.findall("== .*? ===.*?=", output, flags=re.DOTALL)
    }
Exemple #2
0
def cover_pending_counter(bld: Builder):
    m = Module()

    m.submodules.pc = pc = PendingCounter(3, 5)

    was_full = Signal()
    was_emptied = Signal()

    m.d.comb += pc.i_remove.eq(AnySeq(1))
    m.d.comb += Assume(~(pc.i_remove & ~pc.o_any))
    m.d.comb += Assume(~(~pc.i_remove & pc.o_full))

    with m.If(pc.o_full):
        m.d.sync += was_full.eq(1)
    with m.If(~pc.o_any & was_full):
        m.d.sync += was_emptied.eq(1)
    m.d.comb += Cover(was_emptied)

    with bld.temp_open("formal.il") as f:
        il_text = rtlil.convert(m, ports=[pc.pending, pc.timer])
        f.write(il_text)

    sby.verify(
        bld,
        "formal.sby",
        "formal.il",
        sby.Task("sby", "cover", depth=40, engines=["smtbmc", "yices"]),
    )
Exemple #3
0
    def build(self, elaboratable, *, build_dir, **kwargs):

        sim = Simulator(elaboratable)

        os.makedirs(build_dir, exist_ok=True)
        cwd = os.getcwd()
        try:
            os.chdir(build_dir)
            with open("top.il", "w", encoding="utf-8") as f:
                f.write(rtlil.convert(elaboratable))
            with open("top.v", "w", encoding="utf-8") as f:
                f.write(verilog.convert(elaboratable))

            for name, number in self.resources:
                clock = self.lookup(name, number).clock
                if clock is not None:
                    sim.add_clock(clock.period, domain=name)

            for process in self.processes:
                sim.add_sync_process(process)

            for domain, sync_processes in self.sync_processes.items():
                for sync_process in sync_processes:
                    sim.add_sync_process(sync_process, domain=domain)

            with sim.write_vcd("top.vcd"):
                sim.run()
        finally:
            os.chdir(cwd)
def main(cls, filename="toplevel.il"):
    """Runs a file in simulate or generate mode.

    Add this to your file:

        from util import main

        if __name__ == "__main__":
            main(YourClass)

    Then, you can run the file in simulate or generate mode:

    python <file.py> sim will run YourClass.sim and output to whatever vcd
        file you wrote to.
    python <file.py> gen will run YourClass.formal and output in RTLIL format
        to toplevel.il. You can then formally verify using
        sby -f <file.sby>.
    """

    if len(sys.argv) < 2 or (sys.argv[1] != "sim" and sys.argv[1] != "gen"):
        print(f"Usage: python3 {sys.argv[0]} sim|gen")
        sys.exit(1)

    if sys.argv[1] == "sim":
        cls.sim()
    else:
        design, ports = cls.formal()
        fragment = Fragment.get(design, None)
        output = rtlil.convert(fragment, ports=ports)
        with open(filename, "w") as f:
            f.write(output)
Exemple #5
0
def get_size(module, *args, **kwargs):
    rtlil_text = rtlil.convert(module, *args, **kwargs)

    script = """
        read_ilang <<rtlil
        {}
        rtlil
        flatten
        
        synth_ecp5 -abc9
    """.format(rtlil_text)

    popen = subprocess.Popen(["yosys", "-s", "-"],
                             stdin=subprocess.PIPE,
                             stdout=subprocess.PIPE,
                             stderr=subprocess.PIPE,
                             encoding="utf-8")
    output, error = popen.communicate(script)

    print(output)

    try:
        cells = int(re.search("LUT4\\W*(\\d+)", output).group(1))
    except:
        cells = 0

    return cells
Exemple #6
0
def assert_formal(spec, mode="bmc", depth=1):
    functions = []
    test_class = None
    caller_path = ""
    stack = inspect.stack()
    for frame in stack[1:]:
        if "unittest" in frame.filename:
            filename = "__".join(reversed(functions))
            if test_class:
                filename = f'{test_class}__{filename}'
            break
        functions.append(frame.function)
        try:
            test_class = frame.frame.f_locals['self'].__class__.__name__
        except:
            pass
        caller_path = frame.filename

    target_dir = Path(caller_path).parent / ".sim_results"
    target_dir.mkdir(exist_ok=True)
    if (target_dir / filename).exists():
        rmtree(target_dir / filename)

    if mode == "hybrid":
        # A mix of BMC and k-induction, as per personal communication with Claire Wolf.
        script = "setattr -unset init w:* a:nmigen.sample_reg %d"
        mode = "bmc"
    else:
        script = ""

    config = textwrap.dedent("""\
        [options]
        mode {mode}
        depth {depth}
        wait on
        [engines]
        smtbmc
        [script]
        read_ilang top.il
        prep
        {script}
        [file top.il]
        {rtlil}
    """).format(mode=mode,
                depth=depth,
                script=script,
                rtlil=rtlil.convert(Fragment.get(spec,
                                                 platform=FormalPlatform)))
    with subprocess.Popen([require_tool("sby"), "-f", "-d", filename],
                          cwd=str(target_dir),
                          universal_newlines=True,
                          stdin=subprocess.PIPE,
                          stdout=subprocess.PIPE) as proc:
        stdout, stderr = proc.communicate(config)
        if proc.returncode != 0:
            assert False, "Formal verification failed:\n" + stdout + "\n\n" + f"vcd: {str(target_dir / filename)}/engine_0/trace.vcd"
Exemple #7
0
    def assertFormal(self, spec, mode="bmc", depth=1):
        stack = traceback.extract_stack()
        for frame in reversed(stack):
            if os.path.dirname(__file__) not in frame.filename:
                break
            caller = frame

        spec_root, _ = os.path.splitext(caller.filename)
        spec_dir = os.path.dirname(spec_root)
        spec_name = "{}_{}".format(
            os.path.basename(spec_root).replace("test_", "spec_"),
            caller.name.replace("test_", ""))

        # The sby -f switch seems not fully functional when sby is reading from stdin.
        if os.path.exists(os.path.join(spec_dir, spec_name)):
            shutil.rmtree(os.path.join(spec_dir, spec_name))

        if mode == "hybrid":
            # A mix of BMC and k-induction, as per personal communication with Claire Wolf.
            script = "setattr -unset init w:* a:nmigen.sample_reg %d"
            mode = "bmc"
        else:
            script = ""

        config = textwrap.dedent("""\
        [options]
        mode {mode}
        depth {depth}
        wait on

        [engines]
        smtbmc

        [script]
        read_ilang top.il
        prep
        {script}

        [file top.il]
        {rtlil}
        """).format(mode=mode,
                    depth=depth,
                    script=script,
                    rtlil=rtlil.convert(Fragment.get(spec, platform="formal")))
        with subprocess.Popen([require_tool("sby"), "-f", "-d", spec_name],
                              cwd=spec_dir,
                              env={
                                  **os.environ, "PYTHONWARNINGS": "ignore"
                              },
                              universal_newlines=True,
                              stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE) as proc:
            stdout, stderr = proc.communicate(config)
            if proc.returncode != 0:
                self.fail("Formal verification failed:\n" + stdout)
Exemple #8
0
    def build(self, elaboratable, *, build_dir, **kwargs):

        print("Here")

        os.makedirs(build_dir, exist_ok=True)
        cwd = os.getcwd()
        try:
            os.chdir(build_dir)
            with open("top.il", "w", encoding="utf-8") as f:
                f.write(rtlil.convert(elaboratable))
        finally:
            os.chdir(cwd)
Exemple #9
0
    def assertFormal(self, spec, mode="bmc", depth=1):
        """
        mode: bmc, prove
        """

        caller, *_ = traceback.extract_stack(limit=2)
        spec_root, _ = os.path.splitext(caller.filename)
        spec_dir = os.path.dirname(spec_root)
        spec_name = "{}_{}".format(
            os.path.basename(spec_root).replace("test_", "spec_"),
            caller.name.replace("test_", ""))

        # The sby -f switch seems not fully functional when sby is reading from stdin.
        if os.path.exists(os.path.join(spec_dir, spec_name)):
            shutil.rmtree(os.path.join(spec_dir, spec_name))

        config = textwrap.dedent("""\
        [options]
        mode {mode}
        depth {depth}
        wait on

        [engines]
        smtbmc

        [script]
        read_ilang top.il
        prep

        [file top.il]
        {rtlil}
        """).format(mode=mode,
                    depth=depth,
                    rtlil=rtlil.convert(Fragment.get(spec, platform="formal")))
        f = open(os.path.join(spec_dir, spec_name + '.script'), "w")
        f.write(config)
        f.close()
        with subprocess.Popen([require_tool("sby"), "-f", "-d", spec_name],
                              cwd=spec_dir,
                              universal_newlines=True,
                              stdin=subprocess.PIPE,
                              stdout=subprocess.PIPE) as proc:
            stdout, stderr = proc.communicate(config)
            if proc.returncode != 0:
                self.fail("Formal verification failed:\n" + stdout)
Exemple #10
0
def bmc_pending_counter(bld: Builder):
    m = Module()

    m.submodules.pc = pc = PendingCounter(3, 5)

    m.d.comb += pc.i_remove.eq(AnySeq(1))
    m.d.comb += Assume(~(pc.i_remove & ~pc.o_any))
    m.d.comb += Assume(~(~pc.i_remove & pc.o_full))

    with bld.temp_open("formal.il") as f:
        il_text = rtlil.convert(m, ports=[pc.pending, pc.timer])
        f.write(il_text)

    sby.verify(
        bld,
        "formal.sby",
        "formal.il",
        sby.Task("sby", "bmc", depth=40, engines=["smtbmc", "yices"]),
    )
Exemple #11
0
def build_formal_pipe(bld: Builder):
    m = Module()

    in_data = AnySeq(8)
    en_data = AnySeq(1)
    hsync = AnySeq(1)
    vsync = AnySeq(1)

    enc_char_comb = Signal(10)
    enc_char_pipe = Signal(10)

    m.submodules.enc_comb = enc_comb = TMDSEncoder(pipeline=False)
    m.submodules.enc_pipe = enc_pipe = TMDSEncoder(pipeline=True)

    m.d.comb += [
        enc_pipe.i_data.eq(in_data),
        enc_pipe.i_en_data.eq(en_data),
        enc_pipe.i_hsync.eq(hsync),
        enc_pipe.i_vsync.eq(vsync),
        enc_char_pipe.eq(enc_pipe.o_char),
    ]

    m.d.sync += [
        enc_comb.i_data.eq(in_data),
        enc_comb.i_en_data.eq(en_data),
        enc_comb.i_hsync.eq(hsync),
        enc_comb.i_vsync.eq(vsync),
    ]
    m.d.comb += [
        enc_char_comb.eq(enc_comb.o_char),
    ]

    with m.If(~Initial()):
        m.d.comb += [
            Assert(enc_char_pipe == enc_char_comb),
            Assert(enc_pipe.dc_bias == enc_comb.dc_bias),
        ]

    with bld.temp_open("formal.il") as f:
        il_text = rtlil.convert(m, ports=[enc_char_comb, enc_char_pipe])
        f.write(il_text)
Exemple #12
0
def synth(core, ports):
    plat = EmptyPlatform()
    frag = Fragment.get(core, plat)
    rtlil_text = rtlil.convert(frag, ports=ports)

    yosys_cmd = ''
    with tempfile.TemporaryDirectory() as temp_dir:
        with open(temp_dir + '/top.il', 'w') as f:
            f.write(rtlil_text)

        for file_name, content in plat.extra_files.items():
            with open(temp_dir + '/' + file_name, 'wb') as f:
                f.write(content)
            yosys_cmd += "read_verilog {}\n".format(file_name)
        yosys_cmd += 'read_ilang {}\n'.format('top.il')
        yosys_cmd += 'synth_xilinx -top top\n'

        with open(temp_dir + '/top.ys', 'w') as f:
            f.write(yosys_cmd)

        subprocess.check_call([require_tool("yosys"), 'top.ys'], cwd=temp_dir)
Exemple #13
0
 def _generate(self):
     args = self.args
     fragment = Fragment.get(self.design, self.platform)
     generate_type = args.generate_type
     if generate_type is None and args.generate_file:
         if args.generate_file.name.endswith(".v"):
             generate_type = "v"
         if args.generate_file.name.endswith(".il"):
             generate_type = "il"
     if generate_type is None:
         parser.error("specify file type explicitly with -t")
     if generate_type == "il":
         output = rtlil.convert(fragment,
                                name=self.name,
                                ports=self._get_ports())
     if generate_type == "v":
         output = verilog.convert(fragment,
                                  name=self.name,
                                  ports=self._get_ports())
     if args.generate_file:
         args.generate_file.write(output)
     else:
         print(output)
Exemple #14
0
def check(nmigen_module, ports):
    with TemporaryDirectory() as tmpdirname:
        temp_path = pathlib.Path(tmpdirname)
        with open(temp_path / 'out.il', 'w') as f:
            f.write(rtlil.convert(nmigen_module, ports=ports))
        sby_data = f'''
[options]
mode bmc

[engines]
smtbmc z3

[script]
read_ilang out.il
prep -top top

[files]
{temp_path/'out.il'}'''
        with open(temp_path/'out.sby', 'w') as f:
            f.write(sby_data)
        yosys_path = shutil.which('yowasp-yosys')
        smt_path = shutil.which('yowasp-yosys-smtbmc')
        process = subprocess.run([
            'yowasp-sby',
            '-f',
            '-d', temp_path / 'work',
            '--yosys', yosys_path,
            '--smtbmc', smt_path,
            temp_path/'out.sby'], stdout=subprocess.PIPE)
        stdout = str(process.stdout)
        if process.returncode == 0:
            return BMC_Result(Result.PASS, stdout)
        if process.returncode == 1:
            return _get_failure_info(stdout, temp_path / 'work/engine_0/trace.vcd')
        else:
            return BMC_Result(Result.ERROR, stdout)
Exemple #15
0
    ports = [
        dda.i_x0, dda.i_y0, dda.i_r0, dda.i_g0, dda.i_b0,
        dda.i_x1, dda.i_y1, dda.i_r1, dda.i_g1, dda.i_b1,
        dda.i_start, dda.i_next,
        dda.o_x, dda.o_y,
        dda.o_valid, dda.o_last
    ]

    gtkw = open("sim.gtkw", "w")
    vcd = open("sim.vcd", "w")

    with open("line.v", "w") as f:
        f.write(verilog.convert(dda, ports=ports))

    with open("line.il", "w") as f:
        f.write(rtlil.convert(dda, ports=ports))
    
    def line_test(start, end, points):
        print("// ", start, "-> ", end)
        yield dda.i_x0.eq(start[0] << 4)
        yield dda.i_y0.eq(start[1] << 4)
        yield dda.i_x1.eq(end[0] << 4)
        yield dda.i_y1.eq(end[1] << 4)
        yield dda.i_start.eq(1)
        yield dda.i_next.eq(0)
        
        # Wait for setup
        yield; yield
        yield dda.i_start.eq(0)
        yield; yield; yield
Exemple #16
0
                    # Load the immediate register
                    self.o_immediate.eq(imm16),
                    self.o_use_imm.eq(1),
                    # Select the appropriate ALU op.
                    self.o_adder_op.eq(ALUAdder.Add),
                    # These are legal instructions.
                    self.o_ri_except.eq(0),
                    # "signed" instructions trap on overflow here.
                    self.o_ovf_check.eq(is_signed)
                ]

            with m.Case(Instruction.SLTI, Instruction.SLTIU):
                is_signed = Signal()

                m.d.comb += [
                    is_signed.eq(funct.matches(Function.SLTI)),

                    # Load the immediate register
                    self.o_immediate.eq(imm16),
                    self.o_use_imm.eq(1),
                    # Implement comparisons in terms of subtraction.
                    self.o_adder_op.eq(ALUAdder.Sub),
                    # These are legal instructions.
                    self.o_emu_abort.eq(0)
                ]

        return m


rtlil.convert(Decoder())
Exemple #17
0
    def __init__(self, width):
        self.v = Signal(width, reset=2**width - 1)
        self.o = Signal()
        self.en = Signal()

    def elaborate(self, platform):
        m = Module()
        m.d.sync += self.v.eq(self.v + 1)
        m.d.comb += self.o.eq(self.v[-1])
        return EnableInserter(self.en)(m)


ctr = Counter(width=16)

#print(verilog.convert(ctr, ports=[ctr.o, ctr.en]))
print(rtlil.convert(ctr, ports=[ctr.o, ctr.en]))

sim = pysim.Simulator(ctr)
sim.add_clock(1e-6)


def ce_proc():
    yield
    yield
    yield
    yield ctr.en.eq(1)
    yield
    yield
    yield
    yield ctr.en.eq(0)
    yield
Exemple #18
0
from m68000 import m68000

from nmigen.back import rtlil

mod = m68000()

ports = [sig for attr, sig in vars(mod).items() if attr[:2] in ("i_", "o_")]

rtlil_text = rtlil.convert(mod, platform=None, name="m68000", ports=ports)
print("""
read_ilang <<rtlil
{}
rtlil
proc
flatten
memory_collect
opt -full
clean -purge
write_cxxrtl -O3
""".format(rtlil_text))
Exemple #19
0
from via6522 import via6522

from nmigen.back import rtlil

mod = via6522()

ports = [sig for attr, sig in vars(mod).items() if attr[:2] in ("i_", "o_")]

rtlil_text = rtlil.convert(mod, platform=None, name="via6522", ports=ports)
print("""
read_ilang <<rtlil
{}
rtlil
proc
flatten
memory_collect
opt -full
clean -purge
write_cxxrtl -O3
""".format(rtlil_text))
Exemple #20
0
        with m.If(self.i_enable & (self.i_fbpxfmt != PixelFormat.PSMCT24)):
            m.d.comb += test.eq(self.i_alpha[7] == self.i_mode)
        with m.Else():
            m.d.comb += test.eq(1)

        m.d.sync += [
            self.o_rgbrndr.eq(self.i_rgbrndr & test),
            self.o_arndr.eq(self.i_arndr & test),
            self.o_zrndr.eq(self.i_zrndr & test)
        ]

        return m

if __name__ == "__main__":
    atst = DestinationAlphaTest()

    ports = [
        atst.i_enable, atst.i_mode,

        atst.i_rgbrndr, atst.i_arndr, atst.i_zrndr,
        atst.i_x_coord, atst.i_y_coord, atst.i_z_coord,
        atst.i_red, atst.i_green, atst.i_blue, atst.i_alpha,
        atst.i_fbpxfmt,

        atst.o_rgbrndr, atst.o_arndr, atst.o_zrndr,
        atst.o_x_coord, atst.o_y_coord, atst.o_z_coord,
        atst.o_red, atst.o_green, atst.o_blue, atst.o_alpha,
    ]

    print(rtlil.convert(atst, ports=ports))
Exemple #21
0
def build_formal(bld: Builder):
    m = Module()

    in_data = AnySeq(8)
    en_data = AnySeq(1)
    hsync = AnySeq(1)
    vsync = AnySeq(1)

    enc_char = Signal(10)

    real_chr_bias = Signal(signed(5))
    real_dc_bias = Signal(signed(5))

    m.submodules.enc = enc = TMDSEncoder()
    m.submodules.dec = dec = TMDSDecoder()

    m.d.comb += [
        enc.i_data.eq(in_data),
        enc.i_en_data.eq(en_data),
        enc.i_hsync.eq(hsync),
        enc.i_vsync.eq(vsync),
        dec.i_char.eq(enc.o_char),
        enc_char.eq(enc.o_char),
    ]

    m.d.comb += [
        real_chr_bias.eq(popcount(enc.o_char) - 5),
        Assert(real_dc_bias >= -5),
        Assert(real_dc_bias <= +5),
        Assert(real_dc_bias[:4] == enc.dc_bias),
    ]
    m.d.sync += [
        real_dc_bias.eq(real_dc_bias + real_chr_bias),
    ]

    with m.If(~enc.i_en_data):
        m.d.sync += real_dc_bias.eq(real_dc_bias)

    m.d.comb += Cover(
        (Past(dec.o_en_data, 4) & (Past(enc.o_char, 4)[8:10] == 0b00))
        & (Past(dec.o_en_data, 3) & (Past(enc.o_char, 3)[8:10] == 0b01))
        & (Past(dec.o_en_data, 2) & (Past(enc.o_char, 2)[8:10] == 0b10))
        & (Past(dec.o_en_data, 1) & (Past(enc.o_char, 1)[8:10] == 0b11))
        & (dec.o_vsync))

    m.d.comb += Assert(dec.o_en_data == enc.i_en_data)
    with m.If(dec.o_en_data):
        m.d.comb += Assert(dec.o_data == enc.i_data)

        # Check that XNOR choice matches reference algorithm
        in_pop = Signal(4)
        use_xnor = Signal()
        m.d.comb += [
            in_pop.eq(popcount(in_data)),
            use_xnor.eq((in_pop > 4) | ((in_pop == 4) & (in_data[0] == 0))),
            Assert(enc.o_char[8] == ~use_xnor),
        ]

    with m.Else():
        m.d.comb += [
            Assert(dec.o_hsync == enc.i_hsync),
            Assert(dec.o_vsync == enc.i_vsync),
        ]

    with bld.temp_open("formal.il") as f:
        il_text = rtlil.convert(m,
                                ports=[enc_char, real_chr_bias, real_dc_bias])
        f.write(il_text)
Exemple #22
0
        ablend.i_blend_c,
        ablend.i_blend_d,
        ablend.i_fbred,
        ablend.i_fbgreen,
        ablend.i_fbblue,
        ablend.i_fbalpha,
        ablend.i_rgbrndr,
        ablend.i_arndr,
        ablend.i_zrndr,
        ablend.i_x_coord,
        ablend.i_y_coord,
        ablend.i_z_coord,
        ablend.i_red,
        ablend.i_green,
        ablend.i_blue,
        ablend.i_alpha,
        ablend.i_fbpxfmt,
        ablend.o_rgbrndr,
        ablend.o_arndr,
        ablend.o_zrndr,
        ablend.o_x_coord,
        ablend.o_y_coord,
        ablend.o_z_coord,
        ablend.o_red,
        ablend.o_green,
        ablend.o_blue,
        ablend.o_alpha,
    ]

    print(rtlil.convert(ablend, ports=ports))
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0

from nmigen import *
from nmigen.back import rtlil


class Counter(Elaboratable):
    def __init__(self, width):
        self.v = Signal(width, reset=2**width-1)
        self.o = Signal()

    def elaborate(self, platform):
        m = Module()
        m.d.sync += self.v.eq(self.v + 1)
        m.d.comb += self.o.eq(self.v[-1])
        return m


ctr = Counter(width=16)
print(rtlil.convert(ctr, ports=[ctr.o]))
Exemple #24
0
def main():
    top = Top()
    output = rtlil.convert(Fragment.get(top, None),
                           ports=(top.clk100, top.serial_tx))
    print(output)