Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 0 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@
pkgs = import nixpkgs {
inherit system;
};
peakrdl = lowrisc-nix.packages.${system}.peakrdl;

workspace = uv2nix.lib.workspace.loadWorkspace {workspaceRoot = ./.;};
overlay = workspace.mkPyprojectOverlay {
Expand All @@ -61,7 +60,6 @@
in {
devShells.x86_64-linux.default = pkgs.mkShell {
packages = [env pkgs.uv pkgs.reuse];
buildInputs = [peakrdl];
};
formatter.x86_64-linux = nixpkgs.legacyPackages.x86_64-linux.alejandra;
};
Expand Down
4 changes: 2 additions & 2 deletions rdl2ot/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@

[project]
name = "rdl2ot"
version = "0.3.0"
version = "0.4.0"
description = "An extension of PeakRDL to generate OpenTitan RTL."
requires-python = ">=3.10"
keywords = ["SystemRDL", "OpenTitan", "Codegen"]
readme = "README.md"
dependencies = [
"click>=8.3.0",
"jinja2>=3.1.6",
"systemrdl-compiler>=1.29",
"systemrdl-compiler~=1.32.1",
]

authors = [
Expand Down
8 changes: 4 additions & 4 deletions rdl2ot/src/rdl2ot/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ def main() -> None:
@main.command()
@click.argument(
"input_file",
type=click.Path(writable=True),
type=click.Path(path_type=Path, writable=False),
)
@click.argument(
"out_dir",
default="./result",
type=click.Path(writable=True),
type=click.Path(path_type=Path, writable=True),
)
@click.option(
"--soc",
is_flag=True,
)
def export_rtl(input_file: str, out_dir: str, soc: bool = False) -> None:
def export_rtl(input_file: Path, out_dir: Path, soc: bool = False) -> None:
"""Export opentitan rtl.

INPUT_FILE: The input RDL
Expand All @@ -46,6 +46,6 @@ def export_rtl(input_file: str, out_dir: str, soc: bool = False) -> None:
rdlc.compile_file(input_file)
root = rdlc.elaborate()

rtl_exporter.run(root.top, Path(out_dir), soc)
rtl_exporter.run(root.top, out_dir, soc)

print("Successfully finished!\n")
46 changes: 41 additions & 5 deletions rdl2ot/src/rdl2ot/opentitan.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""Functions with opentitan specific logic."""

import re
from enum import Enum

from systemrdl import node
from systemrdl.rdltypes import AccessType, OnReadType, OnWriteType
Expand Down Expand Up @@ -67,7 +68,7 @@ def needs_int_qe(reg: dict) -> bool:
An internal q-enable means the net may be consumed by other reg logic but will
not be exposed in the package file.
"""
return (bool(reg["async_clk"]) and reg["hw_writable"]) or needs_qe(reg)
return (bool(reg.get("async_clk", False)) and reg["hw_writable"]) or needs_qe(reg)


def get_bit_width(offset: int) -> int:
Expand Down Expand Up @@ -98,11 +99,11 @@ def get_sw_access_enum(field: node.FieldNode) -> str:
return "NONE"


def fields_no_write_en(reg: dict) -> int:
"""Count how many fields has write enable."""
def fields_write_en_mask(reg: dict) -> int:
"""Return a mask of bits mapping to write enable fields."""
res = 0
for idx, field in enumerate(reg["fields"]):
res |= (not needs_we(field)) << idx
res |= int(not needs_we(field)) << idx
return res


Expand All @@ -121,9 +122,44 @@ def is_homogeneous(reg: dict) -> bool:

The offset are excluded from the comparison.
"""
exclude = ["name", "msb", "lsb", "bitmask", "type"]
exclude = ["name", "msb", "lsb", "bitmask", "type", "type_name"]
unamed_fields = [
{key: value for key, value in f.items() if key not in exclude} for f in reg["fields"]
]
names = {re.sub(r"_\d+$", "", f["name"]) for f in reg["fields"]}
return all(f == unamed_fields[0] for f in unamed_fields[1:]) and len(names) == 1


class SigType(Enum):
"""Used to give a signal different purposes."""

NONE = "None"
Interrupt = "Interrupt"
Alert = "Alert"
InterModReqRsp = "InterModReqRsp"
InterModReq = "InterModReq"
InterModRecv = "InterModRecv"
InOut = "InOut"
Input = "Input"
Output = "Output"
Sync = "Sync"

def is_pad(self) -> bool:
"""Check whether a signal is a pad."""
return self in [SigType.InOut, SigType.Input, SigType.Output]

def is_interrupt(self) -> bool:
"""Check whether a signal is a interrupt."""
return self in [SigType.Interrupt]

def is_alert(self) -> bool:
"""Check whether a signal is a alert."""
return self in [SigType.Alert]

def is_inter_module(self) -> bool:
"""Check whether a signal is a inter module."""
return self in [SigType.InterModReqRsp, SigType.InterModReq, SigType.InterModRecv]

def is_sync(self) -> bool:
"""Check whether a signal is used for synchronization."""
return self in [SigType.Sync]
Loading