Skip to content

Commit

Permalink
Add static type hints
Browse files Browse the repository at this point in the history
This makes the code easier to understand and navigate, and also detected a few of bugs:

1. Missing brackets on e.upper. (Fixed)
2. Not strictly related to types, but a lot of the regexes were not raw strings and therefore contained invalid escape sequences. Python prints a warning about these in recent versions. (Fixed)
3. Expression in `process_pseudo_instructions()` that is always false. (Not fixed)
4. Missing definition of `log_and_exit()`. (Fixed)

This is validated via pre-commit in CI.
  • Loading branch information
Timmmm committed Oct 31, 2024
1 parent bd5e598 commit 284a5fa
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 210 deletions.
9 changes: 4 additions & 5 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ repos:
# hooks:
# - id: pylint

# TODO: Enable this when types are added.
# - repo: https://github.com/RobertCraigie/pyright-python
# rev: v1.1.383
# hooks:
# - id: pyright
- repo: https://github.com/RobertCraigie/pyright-python
rev: v1.1.383
hooks:
- id: pyright
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
23 changes: 13 additions & 10 deletions latex_utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
import collections
import copy
import glob
import logging
import os
import pprint
import re
import sys
from typing import TextIO

from constants import *
from shared_utils import *
Expand Down Expand Up @@ -117,7 +112,9 @@ def make_latex_table():
# instructions listed in list_of_instructions will be dumped into latex.
caption = ""
type_list = ["R-type", "I-type", "S-type", "B-type", "U-type", "J-type"]
dataset_list = [(["_i", "32_i"], "RV32I Base Instruction Set", [], False)]
dataset_list: list[tuple[list[str], str, list[str], bool]] = [
(["_i", "32_i"], "RV32I Base Instruction Set", [], False)
]
dataset_list.append((["_i"], "", ["fence_tso", "pause"], True))
make_ext_latex_table(type_list, dataset_list, latex_file, 32, caption)

Expand Down Expand Up @@ -184,7 +181,13 @@ def make_latex_table():
latex_file.close()


def make_ext_latex_table(type_list, dataset, latex_file, ilen, caption):
def make_ext_latex_table(
type_list: "list[str]",
dataset: "list[tuple[list[str], str, list[str], bool]]",
latex_file: TextIO,
ilen: int,
caption: str,
):
"""
For a given collection of extensions this function dumps out a complete
latex table which includes the encodings of the instructions.
Expand Down Expand Up @@ -285,7 +288,7 @@ def make_ext_latex_table(type_list, dataset, latex_file, ilen, caption):

# iterate ovr each instruction type and create a table entry
for t in type_dict:
fields = []
fields: list[tuple[int, int, str]] = []

# first capture all "arguments" of the type (funct3, funct7, rd, etc)
# and capture their positions using arg_lut.
Expand Down Expand Up @@ -332,7 +335,7 @@ def make_ext_latex_table(type_list, dataset, latex_file, ilen, caption):
# for each entry in the dataset create a table
content = ""
for ext_list, title, filter_list, include_pseudo in dataset:
instr_dict = {}
instr_dict: InstrDict = {}

# for all extensions list in ext_list, create a dictionary of
# instructions associated with those extensions.
Expand Down
Loading

0 comments on commit 284a5fa

Please sign in to comment.