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 argparse #185

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
18 changes: 10 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
EXTENSIONS := "rv*" "unratified/rv*"
SPIKE_EXTENSIONS := "rv*" "unratified/rv_*" "unratified/rv32*" "unratified/rv64*"
SPIKE_PSEUDO_OPS := 'pause' 'prefetch_i' 'prefetch_r' 'prefetch_w' 'rstsa16' 'rstsa32' 'srli32_u' 'slli_rv128' 'slli_rv32' 'srai_rv128' 'srai_rv32' 'srli_rv128' 'srli_rv32' 'umax32'
ISASIM_H := ../riscv-isa-sim/riscv/encoding.h
PK_H := ../riscv-pk/machine/encoding.h
ENV_H := ../riscv-tests/env/encoding.h
Expand All @@ -9,38 +11,38 @@ default: everything

.PHONY : everything
everything:
@./parse.py -c -go -chisel -sverilog -rust -latex -spinalhdl $(EXTENSIONS)
@./parse.py -c -go -chisel -sverilog -rust -latex -spinalhdl -include_pseudo -extensions $(EXTENSIONS)

.PHONY : encoding.out.h
encoding.out.h:
@./parse.py -c rv* unratified/rv_* unratified/rv32* unratified/rv64*
@./parse.py -c -include_pseudo -pseudo_ops $(SPIKE_PSEUDO_OPS) -extensions $(SPIKE_EXTENSIONS)

.PHONY : inst.chisel
inst.chisel:
@./parse.py -chisel $(EXTENSIONS)
@./parse.py -chisel -extensions $(EXTENSIONS)

.PHONY : inst.go
inst.go:
@./parse.py -go $(EXTENSIONS)
@./parse.py -go -include_pseudo -extensions $(EXTENSIONS)

.PHONY : latex
latex:
@./parse.py -latex $(EXTENSIONS)
@./parse.py -latex -extensions $(EXTENSIONS)

.PHONY : inst.sverilog
inst.sverilog:
@./parse.py -sverilog $(EXTENSIONS)
@./parse.py -sverilog -extensions $(EXTENSIONS)

.PHONY : inst.rs
inst.rs:
@./parse.py -rust $(EXTENSIONS)
@./parse.py -rust -extensions $(EXTENSIONS)

.PHONY : clean
clean:
rm -f inst* priv-instr-table.tex encoding.out.h

.PHONY : install
install: everything
install: encoding.out.h
set -e; for FILE in $(INSTALL_HEADER_FILES); do cp -f encoding.out.h $$FILE; done

.PHONY: instr-table.tex
Expand Down
189 changes: 98 additions & 91 deletions parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@
import collections
import yaml
import sys
import argparse

pp = pprint.PrettyPrinter(indent=2)
logging.basicConfig(level=logging.INFO, format='%(levelname)s:: %(message)s')
logging.basicConfig(level=logging.DEBUG, format='%(levelname)s:: %(message)s', filename='REFACTORED.log')

def process_enc_line(line, ext):
'''
Expand Down Expand Up @@ -144,7 +145,7 @@ def same_base_ext (ext_name, ext_name_list):
return True
return False

def create_inst_dict(file_filter, include_pseudo=False, include_pseudo_ops=[]):
def create_inst_dict(file_filter, include_pseudo=False, pseudo_ops_list=[]):
'''
This function return a dictionary containing all instructions associated
with an extension defined by the file_filter input. The file_filter input
Expand Down Expand Up @@ -253,68 +254,67 @@ def create_inst_dict(file_filter, include_pseudo=False, include_pseudo_ops=[]):
instr_dict[name] = single_dict

# second pass if for pseudo instructions
logging.debug('Collecting pseudo instructions now')
for f in file_names:
logging.debug(f'Parsing File: {f} for pseudo_ops')
with open(f) as fp:
lines = (line.rstrip()
for line in fp) # All lines including the blank ones
lines = list(line for line in lines if line) # Non-blank lines
lines = list(
line for line in lines
if not line.startswith("#")) # remove comment lines

# go through each line of the file
for line in lines:

# ignore all lines not starting with $pseudo
if '$pseudo' not in line:
continue
logging.debug(f' Processing line: {line}')

# use the regex pseudo_regex from constants.py to find the dependent
# extension, dependent instruction, the pseudo_op in question and
# its encoding
(ext, orig_inst, pseudo_inst, line) = pseudo_regex.findall(line)[0]
ext_file = f'{opcodes_dir}/{ext}'

# check if the file of the dependent extension exist. Throw error if
# it doesn't
if not os.path.exists(ext_file):
ext1_file = f'{opcodes_dir}/unratified/{ext}'
if not os.path.exists(ext1_file):
logging.error(f'Pseudo op {pseudo_inst} in {f} depends on {ext} which is not available')
raise SystemExit(1)
else:
ext_file = ext1_file

# check if the dependent instruction exist in the dependent
# extension. Else throw error.
found = False
for oline in open(ext_file):
if not re.findall(f'^\s*{orig_inst}\s+',oline):
if include_pseudo:
logging.debug('Collecting pseudo instructions now')
for f in file_names:
logging.debug(f'Parsing File: {f} for pseudo_ops')
with open(f) as fp:
lines = (line.rstrip()
for line in fp) # All lines including the blank ones
lines = list(line for line in lines if line) # Non-blank lines
lines = list(
line for line in lines
if not line.startswith("#")) # remove comment lines

# go through each line of the file
for line in lines:

# ignore all lines not starting with $pseudo
if '$pseudo' not in line:
continue
else:
found = True
break
if not found:
logging.error(f'Orig instruction {orig_inst} not found in {ext}. Required by pseudo_op {pseudo_inst} present in {f}')
raise SystemExit(1)

logging.debug(f' Processing line: {line}')

# use the regex pseudo_regex from constants.py to find the dependent
# extension, dependent instruction, the pseudo_op in question and
# its encoding
(ext, orig_inst, pseudo_inst, line) = pseudo_regex.findall(line)[0]
ext_file = f'{opcodes_dir}/{ext}'

# check if the file of the dependent extension exist. Throw error if
# it doesn't
if not os.path.exists(ext_file):
ext1_file = f'{opcodes_dir}/unratified/{ext}'
if not os.path.exists(ext1_file):
logging.error(f'Pseudo op {pseudo_inst} in {f} depends on {ext} which is not available')
raise SystemExit(1)
else:
ext_file = ext1_file

# check if the dependent instruction exist in the dependent
# extension. Else throw error.
found = False
for oline in open(ext_file):
if not re.findall(f'^\s*{orig_inst}\s+',oline):
continue
else:
found = True
break
if not found:
logging.error(f'Orig instruction {orig_inst} not found in {ext}. Required by pseudo_op {pseudo_inst} present in {f}')
raise SystemExit(1)

(name, single_dict) = process_enc_line(pseudo_inst + ' ' + line, f)
# add the pseudo_op to the dictionary only if the original
# instruction is not already in the dictionary.
if orig_inst.replace('.','_') not in instr_dict \
or include_pseudo \
or name in include_pseudo_ops:
(name, single_dict) = process_enc_line(pseudo_inst + ' ' + line, f)
# add the pseudo_op to the dictionary only if the original
# instruction is not already in the dictionary.
if orig_inst.replace('.','_') not in instr_dict \
or len(pseudo_ops_list) == 0 or name in pseudo_ops_list:

# update the final dict with the instruction
if name not in instr_dict:
instr_dict[name] = single_dict
logging.debug(f' including pseudo_ops:{name}')
else:
logging.debug(f' Skipping pseudo_op {pseudo_inst} since original instruction {orig_inst} already selected in list')
# update the final dict with the instruction
if name not in instr_dict:
instr_dict[name] = single_dict
logging.debug(f' including pseudo_ops:{name}')
else:
logging.debug(f' Skipping pseudo_op {pseudo_inst} since original instruction {orig_inst} already selected in list')

# third pass if for imported instructions
logging.debug('Collecting imported instructions')
Expand Down Expand Up @@ -918,19 +918,19 @@ def make_go(instr_dict):
import "cmd/internal/obj"

type inst struct {
opcode uint32
funct3 uint32
rs2 uint32
csr int64
funct7 uint32
opcode uint32
funct3 uint32
rs2 uint32
csr int64
funct7 uint32
}

func encode(a obj.As) *inst {
switch a {
switch a {
'''

endoffile = ''' }
return nil
return nil
}
'''

Expand Down Expand Up @@ -966,50 +966,57 @@ def signed(value, width):

if __name__ == "__main__":
print(f'Running with args : {sys.argv}')

extensions = sys.argv[1:]
for i in ['-c','-latex','-chisel','-sverilog','-rust', '-go', '-spinalhdl']:
if i in extensions:
extensions.remove(i)
print(f'Extensions selected : {extensions}')

include_pseudo = False
if "-go" in sys.argv[1:]:
include_pseudo = True

instr_dict = create_inst_dict(extensions, include_pseudo)

parser = argparse.ArgumentParser(
prog="RISC-V Opcodes",
description="Generate code to aid in RISC-V instruction manipulation",
)

parser.add_argument('-c', action='store_true')
parser.add_argument('-latex', action='store_true')
parser.add_argument('-chisel', action='store_true')
parser.add_argument('-sverilog', action='store_true')
parser.add_argument('-rust', action='store_true')
parser.add_argument('-go', action='store_true')
parser.add_argument('-spinalhdl', action='store_true')
parser.add_argument('-include_pseudo', action='store_true')
parser.add_argument('-pseudo_ops', nargs='*', default=[])
parser.add_argument('-extensions', nargs='+')

args = parser.parse_args()

print(f'Extensions selected : {args.extensions}')

instr_dict = create_inst_dict(args.extensions, args.include_pseudo, args.pseudo_ops)
with open('instr_dict.yaml', 'w') as outfile:
yaml.dump(instr_dict, outfile, default_flow_style=False)
instr_dict = collections.OrderedDict(sorted(instr_dict.items()))

if '-c' in sys.argv[1:]:
instr_dict_c = create_inst_dict(extensions, False,
include_pseudo_ops=emitted_pseudo_ops)
instr_dict_c = collections.OrderedDict(sorted(instr_dict_c.items()))
make_c(instr_dict_c)
if args.c:
make_c(instr_dict)
logging.info('encoding.out.h generated successfully')

if '-chisel' in sys.argv[1:]:
if args.chisel:
make_chisel(instr_dict)
logging.info('inst.chisel generated successfully')

if '-spinalhdl' in sys.argv[1:]:
if args.spinalhdl:
make_chisel(instr_dict, True)
logging.info('inst.spinalhdl generated successfully')

if '-sverilog' in sys.argv[1:]:
if args.sverilog:
make_sverilog(instr_dict)
logging.info('inst.sverilog generated successfully')

if '-rust' in sys.argv[1:]:
if args.rust:
make_rust(instr_dict)
logging.info('inst.rs generated successfully')

if '-go' in sys.argv[1:]:
if args.go:
make_go(instr_dict)
logging.info('inst.go generated successfully')

if '-latex' in sys.argv[1:]:
if args.latex:
make_latex_table()
logging.info('instr-table.tex generated successfully')
make_priv_latex_table()
Expand Down