Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use Ibex with mainline fusesoc #2238

Open
shareefj opened this issue Jan 3, 2025 · 2 comments
Open

How to use Ibex with mainline fusesoc #2238

shareefj opened this issue Jan 3, 2025 · 2 comments
Labels
Type:Question Questions

Comments

@shareefj
Copy link

shareefj commented Jan 3, 2025

Hi there,

You seem to still be using a custom Fusesoc version that expects a different GAPI structure. The ot branch you recommend using is quite a way behind mainline Fusesoc so what are your plans for merging changes and/or pulling the latest changes into your fork?

Can you expand on the main differences? Is it just related to your generators or are there additional features?

What would be the workaround for anyone needing to use the latest features of Fusesoc? Can the Ibex source be generated and exported using something like the OT vendoring scripts? Just thinking how I can work around this.

@shareefj shareefj added the Type:Question Questions label Jan 3, 2025
@shareefj
Copy link
Author

shareefj commented Jan 3, 2025

Ergh, and you're on an ancient version of Edalize so I can't use that. Any pointers to how I can import the RTL source and ignore your Fusesoc flow would be great.

@shareefj
Copy link
Author

shareefj commented Jan 3, 2025

I've deleted my previous post here and added a new export script. This clones the Ibex repo, runs your version of Fusesoc to export the RTL, and then post processes the RTL to uniquify it. In our case we followed the OT naming convensions so have a bunch of prim_ files that clash.

The following Core file enables usage of this exported code base in any other project. I might think about how to combine these two steps at some point if you think it worthwhile.

#!/usr/bin/env python3

import os
import sys
import shutil
import tempfile
import subprocess
import fileinput
import re
import argparse
import logging

logger = logging.getLogger(__name__)


def run_command(cmd, cwd=None):
    try:
        subprocess.run(cmd, cwd=cwd, check=True)
    except subprocess.CalledProcessError as e:
        logger.info(f"Error running command {' '.join(cmd)}: \n{e}")
        sys.exit(1)


def setup_venv(ibex_dir):
    run_command([sys.executable, "-m", "venv", "venv"], cwd=ibex_dir)
    venv_python = os.path.join(ibex_dir, "venv", "bin", "python")
    run_command([venv_python, "-m", "pip", "install", "-U", "pip", "wheel"], cwd=ibex_dir)
    run_command([venv_python, "-m", "pip", "install", "-r", "python-requirements.txt"], cwd=ibex_dir)
    return venv_python


def find_files(build_dir):
    files = []
    for root, _, filenames in os.walk(build_dir):
        for file in filenames:
            if file.endswith(('.sv', '.svh', '.vlt')):
                files.append(os.path.join(root, file))
    return files


def process_file(src, dest_dir, prefix):
    with open(src, 'r') as f:
        content = f.read()

    filename = os.path.basename(src)
    if filename.startswith('prim_') or re.search(r'(module|package)\s+prim_[a-zA-Z0-9_]+', content):
        filename = prefix + filename

    dest = os.path.join(dest_dir, filename)
    shutil.copy2(src, dest)

    patterns = [
        # Package access needs to be first
        (r'\bprim_([a-zA-Z0-9_]+)::([a-zA-Z0-9_]+)', f'{prefix}prim_\\1::\\2'),
        # Enum type names
        (r'\bprim_([a-zA-Z0-9_]+)_e\b', f'{prefix}prim_\\1_e'),
        # Module/interface definitions
        (r'\bmodule\s+prim_([a-zA-Z0-9_]+)\b', f'module {prefix}prim_\\1'),
        (r'\binterface\s+prim_([a-zA-Z0-9_]+)\b', f'interface {prefix}prim_\\1'),
        # General primitive instantiations
        (r'\bprim_([a-zA-Z0-9_]+)\s+', f'{prefix}prim_\\1 '),
        # Include and import statements
        (r'`include\s+"prim_([^"]+)"', f'`include "{prefix}prim_\\1"'),
        (r'import\s+prim_([^;]+);', f'import {prefix}prim_\\1;'),
        # Package definitions
        (r'package\s+prim_([a-zA-Z0-9_]+)\s*;', f'package {prefix}prim_\\1;'),
    ]

    with fileinput.FileInput(dest, inplace=True) as file:
        for line in file:
            for pattern, replacement in patterns:
                line = re.sub(pattern, replacement, line)
            print(line, end='')


def export(export_dir: str, prefix: str):
    with tempfile.TemporaryDirectory() as temp_dir:
        logger.info(f"Created temporary directory: {temp_dir}")

        run_command(["git", "clone", "https://github.com/lowrisc/ibex.git"], cwd=temp_dir)
        ibex_dir = os.path.join(temp_dir, "ibex")

        venv_python = setup_venv(ibex_dir)

        run_command([venv_python, "-m", "fusesoc.main", "--cores-root", ".",
                    "run", "--target=lint", "--setup",
                    "--build-root", "./build/ibex_out",
                    "lowrisc:ibex:ibex_top"], cwd=ibex_dir)

        os.makedirs(export_dir, exist_ok=True)

        build_dir = os.path.join(ibex_dir, "build", "ibex_out", "src")
        files = find_files(build_dir)

        for file in files:
            process_file(file, export_dir, prefix)

        logger.info(f"Files exported to {export_dir}")


def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--prefix",
        "-p",
        default="ot_",
        help="Specify a uniquifying prefix to use on all primitive files"
    )
    parser.add_argument(
        "--export-dir",
        "-e",
        default="export",
        help="Specify an export directory"
    )
    parser.add_argument(
        "--clean",
        "-c",
        action="store_true",
        help="Force deletion of the export directory if it exists"
    )
    parser.add_argument(
        "--verbose",
        "-v",
        action="store_true",
        help="Use verbose logging"
    )
    return parser.parse_args()


def main():
    args = get_args()

    level = logging.INFO
    if args.verbose:
        level = logging.DEBUG
    logging.basicConfig(format="%(levelname)s: %(message)s", level=level)

    if os.path.exists(args.export_dir):
        if not args.clean:
            logger.error(f"export directory already exists; use --clean or pick another directory")
            exit(1)
        shutil.rmtree(args.export_dir)

    export(args.export_dir, args.prefix)


if __name__ == "__main__":
    main()
#ibex.core
CAPI=2:
name: lowrisc:export:ibex_top
description: Ibex CPU source code

filesets:
  rtl:
    files:
      - rtl/dv_fcov_macros.svh: {is_include_file: true}
      - rtl/ot_prim_assert_yosys_macros.svh: {is_include_file: true}
      - rtl/ot_prim_assert_standard_macros.svh: {is_include_file: true}
      - rtl/ot_prim_assert_dummy_macros.svh: {is_include_file: true}
      - rtl/ot_prim_assert_sec_cm.svh: {is_include_file: true}
      - rtl/ot_prim_util_get_scramble_params.svh: {is_include_file: true}
      - rtl/ot_prim_util_memload.svh: {is_include_file: true}
      - rtl/ot_prim_assert.sv
      - rtl/ot_prim_pkg.sv
      - rtl/ot_prim_util_pkg.sv
      - rtl/ot_prim_secded_pkg.sv
      - rtl/ibex_pkg.sv
      - rtl/ot_prim_cipher_pkg.sv
      - rtl/ot_prim_mubi_pkg.sv
      - rtl/ot_prim_count_pkg.sv
      - rtl/ot_prim_ram_1p_pkg.sv
      - rtl/ot_prim_and2.sv
      - rtl/ot_prim_badbit_ram_1p.sv
      - rtl/ot_prim_buf.sv
      - rtl/ot_prim_clock_gating.sv
      - rtl/ot_prim_clock_mux2.sv
      - rtl/ot_prim_count.sv
      - rtl/ot_prim_flop.sv
      - rtl/ot_prim_flop_macros.sv
      - rtl/ot_prim_generic_and2.sv
      - rtl/ot_prim_generic_buf.sv
      - rtl/ot_prim_generic_clock_gating.sv
      - rtl/ot_prim_generic_clock_mux2.sv
      - rtl/ot_prim_generic_flop.sv
      - rtl/ot_prim_generic_ram_1p.sv
      - rtl/ot_prim_lfsr.sv
      - rtl/ot_prim_mubi12_dec.sv
      - rtl/ot_prim_mubi12_sender.sv
      - rtl/ot_prim_mubi12_sync.sv
      - rtl/ot_prim_mubi16_dec.sv
      - rtl/ot_prim_mubi16_sender.sv
      - rtl/ot_prim_mubi16_sync.sv
      - rtl/ot_prim_mubi20_dec.sv
      - rtl/ot_prim_mubi20_sender.sv
      - rtl/ot_prim_mubi20_sync.sv
      - rtl/ot_prim_mubi24_dec.sv
      - rtl/ot_prim_mubi24_sender.sv
      - rtl/ot_prim_mubi24_sync.sv
      - rtl/ot_prim_mubi28_dec.sv
      - rtl/ot_prim_mubi28_sender.sv
      - rtl/ot_prim_mubi28_sync.sv
      - rtl/ot_prim_mubi32_dec.sv
      - rtl/ot_prim_mubi32_sender.sv
      - rtl/ot_prim_mubi32_sync.sv
      - rtl/ot_prim_mubi4_dec.sv
      - rtl/ot_prim_mubi4_sender.sv
      - rtl/ot_prim_mubi4_sync.sv
      - rtl/ot_prim_mubi8_dec.sv
      - rtl/ot_prim_mubi8_sender.sv
      - rtl/ot_prim_mubi8_sync.sv
      - rtl/ot_prim_onehot_check.sv
      - rtl/ot_prim_onehot_enc.sv
      - rtl/ot_prim_onehot_mux.sv
      - rtl/ot_prim_present.sv
      - rtl/ot_prim_prince.sv
      - rtl/ot_prim_ram_1p.sv
      - rtl/ot_prim_ram_1p_adv.sv
      - rtl/ot_prim_ram_1p_scr.sv
      - rtl/ot_prim_secded_22_16_dec.sv
      - rtl/ot_prim_secded_22_16_enc.sv
      - rtl/ot_prim_secded_28_22_dec.sv
      - rtl/ot_prim_secded_28_22_enc.sv
      - rtl/ot_prim_secded_39_32_dec.sv
      - rtl/ot_prim_secded_39_32_enc.sv
      - rtl/ot_prim_secded_64_57_dec.sv
      - rtl/ot_prim_secded_64_57_enc.sv
      - rtl/ot_prim_secded_72_64_dec.sv
      - rtl/ot_prim_secded_72_64_enc.sv
      - rtl/ot_prim_secded_hamming_22_16_dec.sv
      - rtl/ot_prim_secded_hamming_22_16_enc.sv
      - rtl/ot_prim_secded_hamming_39_32_dec.sv
      - rtl/ot_prim_secded_hamming_39_32_enc.sv
      - rtl/ot_prim_secded_hamming_72_64_dec.sv
      - rtl/ot_prim_secded_hamming_72_64_enc.sv
      - rtl/ot_prim_secded_hamming_76_68_dec.sv
      - rtl/ot_prim_secded_hamming_76_68_enc.sv
      - rtl/ot_prim_secded_inv_22_16_dec.sv
      - rtl/ot_prim_secded_inv_22_16_enc.sv
      - rtl/ot_prim_secded_inv_28_22_dec.sv
      - rtl/ot_prim_secded_inv_28_22_enc.sv
      - rtl/ot_prim_secded_inv_39_32_dec.sv
      - rtl/ot_prim_secded_inv_39_32_enc.sv
      - rtl/ot_prim_secded_inv_64_57_dec.sv
      - rtl/ot_prim_secded_inv_64_57_enc.sv
      - rtl/ot_prim_secded_inv_72_64_dec.sv
      - rtl/ot_prim_secded_inv_72_64_enc.sv
      - rtl/ot_prim_secded_inv_hamming_22_16_dec.sv
      - rtl/ot_prim_secded_inv_hamming_22_16_enc.sv
      - rtl/ot_prim_secded_inv_hamming_39_32_dec.sv
      - rtl/ot_prim_secded_inv_hamming_39_32_enc.sv
      - rtl/ot_prim_secded_inv_hamming_72_64_dec.sv
      - rtl/ot_prim_secded_inv_hamming_72_64_enc.sv
      - rtl/ot_prim_secded_inv_hamming_76_68_dec.sv
      - rtl/ot_prim_secded_inv_hamming_76_68_enc.sv
      - rtl/ot_prim_subst_perm.sv
      - rtl/ot_prim_xilinx_and2.sv
      - rtl/ot_prim_xilinx_buf.sv
      - rtl/ot_prim_xilinx_clock_gating.sv
      - rtl/ot_prim_xilinx_clock_mux2.sv
      - rtl/ot_prim_xilinx_flop.sv
      - rtl/ibex_pmp.sv
      - rtl/ibex_load_store_unit.sv
      - rtl/ibex_ex_block.sv
      - rtl/ibex_core.sv
      - rtl/ibex_multdiv_slow.sv
      - rtl/ibex_id_stage.sv
      - rtl/ibex_wb_stage.sv
      - rtl/ibex_prefetch_buffer.sv
      - rtl/ibex_counter.sv
      - rtl/ibex_controller.sv
      - rtl/ibex_branch_predict.sv
      - rtl/ibex_compressed_decoder.sv
      - rtl/ibex_fetch_fifo.sv
      - rtl/ibex_csr.sv
      - rtl/ibex_cs_registers.sv
      - rtl/ibex_dummy_instr.sv
      - rtl/ibex_alu.sv
      - rtl/ibex_if_stage.sv
      - rtl/ibex_decoder.sv
      - rtl/ibex_multdiv_fast.sv
      - rtl/ibex_lockstep.sv
      - rtl/ibex_register_file_latch.sv
      - rtl/ibex_register_file_fpga.sv
      - rtl/ibex_top.sv
      - rtl/ibex_register_file_ff.sv
      - rtl/ibex_icache.sv
    file_type: systemVerilogSource

  verilator_waivers:
    files:
      - rtl/ot_prim_generic_clock_gating.vlt
      - rtl/common.vlt
      - rtl/ot_prim_onehot_check.vlt
      - rtl/ot_prim_cipher.vlt
      - rtl/ot_prim_generic_clock_mux2.vlt
      - rtl/ot_prim_assert.vlt
      - rtl/verilator_waiver.vlt
      - rtl/ot_prim_xilinx_clock_gating.vlt
      - rtl/verilator_waiver.vlt
      - rtl/ot_prim_xilinx_clock_mux2.vlt
      - rtl/ot_prim_count.vlt
      - rtl/ot_prim_ram_1p_scr.vlt
      - rtl/ot_prim_generic_ram_1p.vlt
    file_type: vlt

targets:
  default:
    filesets:
      - rtl
      - tool_verilator ? (verilator_waivers)
    toplevel: ibex_top

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Type:Question Questions
Projects
None yet
Development

No branches or pull requests

1 participant