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

Add static type hints #293

Merged
merged 2 commits into from
Oct 31, 2024
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
3 changes: 1 addition & 2 deletions .github/workflows/python-app.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ jobs:
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install PyYAML
- name: Install Coverage
run: |
pip3 install -r requirements.txt
pip3 install coverage
- name: Run pre-commit
run: |
Expand Down
3 changes: 1 addition & 2 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@ jobs:
uses: actions/setup-python@v2
with:
python-version: 3.8
- name: Install PyYAML
- name: Install Coverage
run: |
pip3 install -r requirements.txt
pip3 install coverage
- name: Test error outputs
run: coverage run -m unittest -b
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ priv-instr-table.tex
inst.rs
inst.spinalhdl
inst.sverilog
instr_dict.yaml
instr_dict.json

__pycache__/
13 changes: 4 additions & 9 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,8 @@ repos:
# rev: v3.3.1
# hooks:
# - id: pylint
# additional_dependencies:
# - "pyyaml==6.0.2"

# TODO: Enable this when types are added.
# - repo: https://github.com/RobertCraigie/pyright-python
# rev: v1.1.383
# hooks:
# - id: pyright
# additional_dependencies:
# - "pyyaml==6.0.2"
- repo: https://github.com/RobertCraigie/pyright-python
rev: v1.1.383
hooks:
- id: pyright
22 changes: 8 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,11 @@ of extensions are being processed such that the *base-instruction* is not includ

The following artifacts can be generated using parse.py:

- instr\_dict.yaml : This is file generated always by parse.py and contains the
entire main dictionary `instr\_dict` in YAML format. Note, in this yaml the
*dots* in an instruction are replaced with *underscores*
- instr\_dict.json : This is always generated by parse.py and contains the
entire main dictionary `instr\_dict` in JSON format. Note, in this file the
*dots* in an instruction are replaced with *underscores*. In previous
versions of this project the generated file was instr\_dict.yaml. Note that
JSON is a subset of YAML so the file can still be read by any YAML parser.
- encoding.out.h : this is the header file that is used by tools like spike, pk, etc
- instr-table.tex : the latex table of instructions used in the riscv-unpriv spec
- priv-instr-table.tex : the latex table of instruction used in the riscv-priv spec
Expand All @@ -138,14 +140,6 @@ The following artifacts can be generated using parse.py:
- inst.spinalhdl : spinalhdl code to decode instructions
- inst.go : go code to decode instructions

Make sure you install the required python pre-requisites are installed by executing the following
command:

```
sudo apt-get install python-pip3
pip3 install -r requirements.txt
```

To generate all the above artifacts for all instructions currently checked in, simply run `make` from the root-directory. This should print the following log on the command-line:

```
Expand Down Expand Up @@ -220,6 +214,6 @@ DEBUG:: Processing line: bne bimm12hi rs1 rs2 bimm12lo 14..12=1 6..2=0x
## How do I find where an instruction is defined?

You can use `grep "^\s*<instr-name>" rv* unratified/rv*` OR run `make` and open
`instr_dict.yaml` and search of the instruction you are looking for. Within that
instruction the `extension` field will indicate which file the instruction was
picked from.
`instr_dict.json` and search for the instruction you are looking for. Within
that instruction the `extension` field will indicate which file the
instruction was picked from.
2 changes: 1 addition & 1 deletion c_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
logging.basicConfig(level=logging.INFO, format="%(levelname)s:: %(message)s")


def make_c(instr_dict):
def make_c(instr_dict: InstrDict):
mask_match_str = ""
declare_insn_str = ""
for i in instr_dict:
Expand Down
4 changes: 2 additions & 2 deletions chisel_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
logging.basicConfig(level=logging.INFO, format="%(levelname)s:: %(message)s")


def make_chisel(instr_dict, spinal_hdl=False):
def make_chisel(instr_dict: InstrDict, spinal_hdl: bool = False):

chisel_names = ""
cause_names_str = ""
Expand All @@ -31,7 +31,7 @@ def make_chisel(instr_dict, spinal_hdl=False):
elif "rv_" in e:
e_format = e.replace("rv_", "").upper()
else:
e_format = e.upper
e_format = e.upper()
chisel_names += f' val {e_format+"Type"} = Map(\n'
for instr in e_instrs:
tmp_instr_name = '"' + instr.upper().replace(".", "_") + '"'
Expand Down
218 changes: 96 additions & 122 deletions constants.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import csv
import re

# TODO: The constants in this file should be in all caps.
overlapping_extensions = {
"rv_zcmt": {"rv_c_d"},
"rv_zcmp": {"rv_c_d"},
Expand All @@ -21,29 +22,29 @@

# regex to find <msb>..<lsb>=<val> patterns in instruction
fixed_ranges = re.compile(
"\s*(?P<msb>\d+.?)\.\.(?P<lsb>\d+.?)\s*=\s*(?P<val>\d[\w]*)[\s$]*", re.M
r"\s*(?P<msb>\d+.?)\.\.(?P<lsb>\d+.?)\s*=\s*(?P<val>\d[\w]*)[\s$]*", re.M
)

# regex to find <lsb>=<val> patterns in instructions
# single_fixed = re.compile('\s+(?P<lsb>\d+)=(?P<value>[\w\d]*)[\s$]*', re.M)
single_fixed = re.compile("(?:^|[\s])(?P<lsb>\d+)=(?P<value>[\w]*)((?=\s|$))", re.M)
single_fixed = re.compile(r"(?:^|[\s])(?P<lsb>\d+)=(?P<value>[\w]*)((?=\s|$))", re.M)

# regex to find the overloading condition variable
var_regex = re.compile("(?P<var>[a-zA-Z][\w\d]*)\s*=\s*.*?[\s$]*", re.M)
var_regex = re.compile(r"(?P<var>[a-zA-Z][\w\d]*)\s*=\s*.*?[\s$]*", re.M)

# regex for pseudo op instructions returns the dependent filename, dependent
# instruction, the pseudo op name and the encoding string
pseudo_regex = re.compile(
"^\$pseudo_op\s+(?P<filename>rv[\d]*_[\w].*)::\s*(?P<orig_inst>.*?)\s+(?P<pseudo_inst>.*?)\s+(?P<overload>.*)$",
r"^\$pseudo_op\s+(?P<filename>rv[\d]*_[\w].*)::\s*(?P<orig_inst>.*?)\s+(?P<pseudo_inst>.*?)\s+(?P<overload>.*)$",
re.M,
)

imported_regex = re.compile(
"^\s*\$import\s*(?P<extension>.*)\s*::\s*(?P<instruction>.*)", re.M
r"^\s*\$import\s*(?P<extension>.*)\s*::\s*(?P<instruction>.*)", re.M
)


def read_csv(filename):
def read_csv(filename: str):
"""
Reads a CSV file and returns a list of tuples.
Each tuple contains an integer value (from the first column) and a string (from the second column).
Expand Down Expand Up @@ -79,126 +80,99 @@ def read_csv(filename):

# dictionary containing the mapping of the argument to the what the fields in
# the latex table should be
latex_mapping = {}
latex_mapping["imm12"] = "imm[11:0]"
latex_mapping["rs1"] = "rs1"
latex_mapping["rs2"] = "rs2"
latex_mapping["rd"] = "rd"
latex_mapping["imm20"] = "imm[31:12]"
latex_mapping["bimm12hi"] = "imm[12$\\vert$10:5]"
latex_mapping["bimm12lo"] = "imm[4:1$\\vert$11]"
latex_mapping["imm12hi"] = "imm[11:5]"
latex_mapping["imm12lo"] = "imm[4:0]"
latex_mapping["jimm20"] = "imm[20$\\vert$10:1$\\vert$11$\\vert$19:12]"
latex_mapping["zimm"] = "uimm"
latex_mapping["shamtw"] = "shamt"
latex_mapping["shamtd"] = "shamt"
latex_mapping["shamtq"] = "shamt"
latex_mapping["rd_p"] = "rd\\,$'$"
latex_mapping["rs1_p"] = "rs1\\,$'$"
latex_mapping["rs2_p"] = "rs2\\,$'$"
latex_mapping["rd_rs1_n0"] = "rd/rs$\\neq$0"
latex_mapping["rd_rs1_p"] = "rs1\\,$'$/rs2\\,$'$"
latex_mapping["c_rs2"] = "rs2"
latex_mapping["c_rs2_n0"] = "rs2$\\neq$0"
latex_mapping["rd_n0"] = "rd$\\neq$0"
latex_mapping["rs1_n0"] = "rs1$\\neq$0"
latex_mapping["c_rs1_n0"] = "rs1$\\neq$0"
latex_mapping["rd_rs1"] = "rd/rs1"
latex_mapping["zimm6hi"] = "uimm[5]"
latex_mapping["zimm6lo"] = "uimm[4:0]"
latex_mapping["c_nzuimm10"] = "nzuimm[5:4$\\vert$9:6$\\vert$2$\\vert$3]"
latex_mapping["c_uimm7lo"] = "uimm[2$\\vert$6]"
latex_mapping["c_uimm7hi"] = "uimm[5:3]"
latex_mapping["c_uimm8lo"] = "uimm[7:6]"
latex_mapping["c_uimm8hi"] = "uimm[5:3]"
latex_mapping["c_uimm9lo"] = "uimm[7:6]"
latex_mapping["c_uimm9hi"] = "uimm[5:4$\\vert$8]"
latex_mapping["c_nzimm6lo"] = "nzimm[4:0]"
latex_mapping["c_nzimm6hi"] = "nzimm[5]"
latex_mapping["c_imm6lo"] = "imm[4:0]"
latex_mapping["c_imm6hi"] = "imm[5]"
latex_mapping["c_nzimm10hi"] = "nzimm[9]"
latex_mapping["c_nzimm10lo"] = "nzimm[4$\\vert$6$\\vert$8:7$\\vert$5]"
latex_mapping["c_nzimm18hi"] = "nzimm[17]"
latex_mapping["c_nzimm18lo"] = "nzimm[16:12]"
latex_mapping["c_imm12"] = (
"imm[11$\\vert$4$\\vert$9:8$\\vert$10$\\vert$6$\\vert$7$\\vert$3:1$\\vert$5]"
)
latex_mapping["c_bimm9lo"] = "imm[7:6$\\vert$2:1$\\vert$5]"
latex_mapping["c_bimm9hi"] = "imm[8$\\vert$4:3]"
latex_mapping["c_nzuimm5"] = "nzuimm[4:0]"
latex_mapping["c_nzuimm6lo"] = "nzuimm[4:0]"
latex_mapping["c_nzuimm6hi"] = "nzuimm[5]"
latex_mapping["c_uimm8splo"] = "uimm[4:2$\\vert$7:6]"
latex_mapping["c_uimm8sphi"] = "uimm[5]"
latex_mapping["c_uimm8sp_s"] = "uimm[5:2$\\vert$7:6]"
latex_mapping["c_uimm10splo"] = "uimm[4$\\vert$9:6]"
latex_mapping["c_uimm10sphi"] = "uimm[5]"
latex_mapping["c_uimm9splo"] = "uimm[4:3$\\vert$8:6]"
latex_mapping["c_uimm9sphi"] = "uimm[5]"
latex_mapping["c_uimm10sp_s"] = "uimm[5:4$\\vert$9:6]"
latex_mapping["c_uimm9sp_s"] = "uimm[5:3$\\vert$8:6]"
latex_mapping = {
"imm12": "imm[11:0]",
"rs1": "rs1",
"rs2": "rs2",
"rd": "rd",
"imm20": "imm[31:12]",
"bimm12hi": "imm[12$\\vert$10:5]",
"bimm12lo": "imm[4:1$\\vert$11]",
"imm12hi": "imm[11:5]",
"imm12lo": "imm[4:0]",
"jimm20": "imm[20$\\vert$10:1$\\vert$11$\\vert$19:12]",
"zimm": "uimm",
"shamtw": "shamt",
"shamtd": "shamt",
"shamtq": "shamt",
"rd_p": "rd\\,$'$",
"rs1_p": "rs1\\,$'$",
"rs2_p": "rs2\\,$'$",
"rd_rs1_n0": "rd/rs$\\neq$0",
"rd_rs1_p": "rs1\\,$'$/rs2\\,$'$",
"c_rs2": "rs2",
"c_rs2_n0": "rs2$\\neq$0",
"rd_n0": "rd$\\neq$0",
"rs1_n0": "rs1$\\neq$0",
"c_rs1_n0": "rs1$\\neq$0",
"rd_rs1": "rd/rs1",
"zimm6hi": "uimm[5]",
"zimm6lo": "uimm[4:0]",
"c_nzuimm10": "nzuimm[5:4$\\vert$9:6$\\vert$2$\\vert$3]",
"c_uimm7lo": "uimm[2$\\vert$6]",
"c_uimm7hi": "uimm[5:3]",
"c_uimm8lo": "uimm[7:6]",
"c_uimm8hi": "uimm[5:3]",
"c_uimm9lo": "uimm[7:6]",
"c_uimm9hi": "uimm[5:4$\\vert$8]",
"c_nzimm6lo": "nzimm[4:0]",
"c_nzimm6hi": "nzimm[5]",
"c_imm6lo": "imm[4:0]",
"c_imm6hi": "imm[5]",
"c_nzimm10hi": "nzimm[9]",
"c_nzimm10lo": "nzimm[4$\\vert$6$\\vert$8:7$\\vert$5]",
"c_nzimm18hi": "nzimm[17]",
"c_nzimm18lo": "nzimm[16:12]",
"c_imm12": "imm[11$\\vert$4$\\vert$9:8$\\vert$10$\\vert$6$\\vert$7$\\vert$3:1$\\vert$5]",
"c_bimm9lo": "imm[7:6$\\vert$2:1$\\vert$5]",
"c_bimm9hi": "imm[8$\\vert$4:3]",
"c_nzuimm5": "nzuimm[4:0]",
"c_nzuimm6lo": "nzuimm[4:0]",
"c_nzuimm6hi": "nzuimm[5]",
"c_uimm8splo": "uimm[4:2$\\vert$7:6]",
"c_uimm8sphi": "uimm[5]",
"c_uimm8sp_s": "uimm[5:2$\\vert$7:6]",
"c_uimm10splo": "uimm[4$\\vert$9:6]",
"c_uimm10sphi": "uimm[5]",
"c_uimm9splo": "uimm[4:3$\\vert$8:6]",
"c_uimm9sphi": "uimm[5]",
"c_uimm10sp_s": "uimm[5:4$\\vert$9:6]",
"c_uimm9sp_s": "uimm[5:3$\\vert$8:6]",
}

# created a dummy instruction-dictionary like dictionary for all the instruction
# types so that the same logic can be used to create their tables
latex_inst_type = {}
latex_inst_type["R-type"] = {}
latex_inst_type["R-type"]["variable_fields"] = [
"opcode",
"rd",
"funct3",
"rs1",
"rs2",
"funct7",
]
latex_inst_type["R4-type"] = {}
latex_inst_type["R4-type"]["variable_fields"] = [
"opcode",
"rd",
"funct3",
"rs1",
"rs2",
"funct2",
"rs3",
]
latex_inst_type["I-type"] = {}
latex_inst_type["I-type"]["variable_fields"] = [
"opcode",
"rd",
"funct3",
"rs1",
"imm12",
]
latex_inst_type["S-type"] = {}
latex_inst_type["S-type"]["variable_fields"] = [
"opcode",
"imm12lo",
"funct3",
"rs1",
"rs2",
"imm12hi",
]
latex_inst_type["B-type"] = {}
latex_inst_type["B-type"]["variable_fields"] = [
"opcode",
"bimm12lo",
"funct3",
"rs1",
"rs2",
"bimm12hi",
latex_inst_type = {
"R-type": {
"variable_fields": ["opcode", "rd", "funct3", "rs1", "rs2", "funct7"],
},
"R4-type": {
"variable_fields": ["opcode", "rd", "funct3", "rs1", "rs2", "funct2", "rs3"],
},
"I-type": {
"variable_fields": ["opcode", "rd", "funct3", "rs1", "imm12"],
},
"S-type": {
"variable_fields": ["opcode", "imm12lo", "funct3", "rs1", "rs2", "imm12hi"],
},
"B-type": {
"variable_fields": ["opcode", "bimm12lo", "funct3", "rs1", "rs2", "bimm12hi"],
},
"U-type": {
"variable_fields": ["opcode", "rd", "imm20"],
},
"J-type": {
"variable_fields": ["opcode", "rd", "jimm20"],
},
}
latex_fixed_fields = [
(31, 25),
(24, 20),
(19, 15),
(14, 12),
(11, 7),
(6, 0),
]
latex_inst_type["U-type"] = {}
latex_inst_type["U-type"]["variable_fields"] = ["opcode", "rd", "imm20"]
latex_inst_type["J-type"] = {}
latex_inst_type["J-type"]["variable_fields"] = ["opcode", "rd", "jimm20"]
latex_fixed_fields = []
latex_fixed_fields.append((31, 25))
latex_fixed_fields.append((24, 20))
latex_fixed_fields.append((19, 15))
latex_fixed_fields.append((14, 12))
latex_fixed_fields.append((11, 7))
latex_fixed_fields.append((6, 0))

# Pseudo-ops present in the generated encodings.
# By default pseudo-ops are not listed as they are considered aliases
Expand Down
2 changes: 1 addition & 1 deletion go_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
logging.basicConfig(level=logging.INFO, format="%(levelname)s:: %(message)s")


def make_go(instr_dict):
def make_go(instr_dict: InstrDict):

args = " ".join(sys.argv)
prelude = f"""// Code generated by {args}; DO NOT EDIT."""
Expand Down
Loading
Loading