diff --git a/.gitignore b/.gitignore index cf3feec..1a32213 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ dist riscv_assembler.egg-info build .pytest_cache/ -deprc_setup.py \ No newline at end of file +deprc_setup.py +__pycache__/ \ No newline at end of file diff --git a/src/riscv_assembler/__pycache__/convert.cpython-38.pyc b/src/riscv_assembler/__pycache__/convert.cpython-38.pyc index 456c6d2..8ab836d 100644 Binary files a/src/riscv_assembler/__pycache__/convert.cpython-38.pyc and b/src/riscv_assembler/__pycache__/convert.cpython-38.pyc differ diff --git a/src/riscv_assembler/__pycache__/instr_arr.cpython-38.pyc b/src/riscv_assembler/__pycache__/instr_arr.cpython-38.pyc index 18b4a22..ba150fa 100644 Binary files a/src/riscv_assembler/__pycache__/instr_arr.cpython-38.pyc and b/src/riscv_assembler/__pycache__/instr_arr.cpython-38.pyc differ diff --git a/src/riscv_assembler/__pycache__/parse.cpython-38.pyc b/src/riscv_assembler/__pycache__/parse.cpython-38.pyc index cf5d258..dbb86b1 100644 Binary files a/src/riscv_assembler/__pycache__/parse.cpython-38.pyc and b/src/riscv_assembler/__pycache__/parse.cpython-38.pyc differ diff --git a/src/riscv_assembler/instr_arr.py b/src/riscv_assembler/instr_arr.py index 91f4aa2..27f1bd8 100644 --- a/src/riscv_assembler/instr_arr.py +++ b/src/riscv_assembler/instr_arr.py @@ -4,7 +4,7 @@ __all__ = [ 'R_instr', 'I_instr', 'S_instr', - 'SB_instr', 'U_instr', 'UJ_instr','pseudo_instr', + 'SB_instr', 'U_instr', 'UJ_instr','pseudo_instr', 'JUMP', 'R', 'I', 'S', 'SB', 'U', 'UJ', 'Rp', 'Ip', 'Sp', 'SBp', 'Up', 'UJp', 'Psp'] @@ -69,7 +69,8 @@ def compute_instr(self, instr, rs1, imm, rd): @staticmethod def immediate(imm): #return int(imm) - ((int(imm)>>12)<<12) # imm[11:0] - return format(int(imm), '012b') + return format(((1 << 12) - 1) & int(imm), '012b') + #return format(int(imm), '012b') class _S(Instruction): def __repr__(self): @@ -97,7 +98,7 @@ def immediate(imm, n): mod_imm_2 = int(imm) - ((int(imm) >> 5) << 5) # imm[4:0] return mod_imm, mod_imm_2''' - mod_imm = format(((1 << 13) - 1) & int(imm), '013b') + mod_imm = format(((1 << 12) - 1) & int(imm), '012b') if n == 1: return mod_imm[0] + mod_imm[12-10 : 12-4] return mod_imm[12-4 : 12 - 0] + mod_imm[1] @@ -127,8 +128,8 @@ def compute_instr(self, instr, rs1, rs2, imm): def immediate(imm, n): mod_imm = format(((1 << 13) - 1) & int(imm), '013b') if n == 1: - return mod_imm[12-12] + mod_imm[12-10:12-5] - return mod_imm[12-4:12-1] + mod_imm[12-11] + return mod_imm[12-12] + mod_imm[12-11:12-5] + return mod_imm[12-4:12-0] + mod_imm[12-11] class _U(Instruction): def __repr__(self): @@ -201,10 +202,11 @@ def __str__(self): return "I Parser" def organize(self, tokens): + line_num, code = tokens[-2], tokens[-1] instr, rs1, imm, rd = tokens[0], None, None, None if instr == "jalr": if len(tokens) == 4: - rs1, imm, rd = reg_map[tokens[2]], JUMP(tokens[3]), reg_map[tokens[1]] + rs1, imm, rd = reg_map[tokens[2]], JUMP(tokens[3], line_num, code), reg_map[tokens[1]] else: rs1, imm, rd = reg_map[tokens[1]], 0, reg_map["x1"] elif instr == "lw": @@ -235,7 +237,8 @@ def __str__(self): return "SB Parser" def organize(self, tokens): - instr, rs1, rs2, imm = tokens[0], reg_map[tokens[1]], reg_map[tokens[2]], JUMP(tokens[3]) + line_num, code = tokens[-2], tokens[-1] + instr, rs1, rs2, imm = tokens[0], reg_map[tokens[1]], reg_map[tokens[2]], JUMP(tokens[3], line_num, code) return SB(instr, rs1, rs2, imm) class _U_parse(InstructionParser): @@ -259,11 +262,12 @@ def __str__(self): return "UJ Parser" def organize(self, tokens): + line_num, code = tokens[-2], tokens[-1] instr, imm, rd = tokens[0], None, None if len(tokens) == 3: - imm, rd = JUMP(tokens[2]), reg_map[tokens[1]] + imm, rd = JUMP(tokens[2], line_num, code), reg_map[tokens[1]] else: - imm, rd = JUMP(tokens[1]), reg_map["x1"] + imm, rd = JUMP(tokens[1], line_num, code), reg_map["x1"] return UJ(instr, imm, rd) @@ -292,27 +296,25 @@ def organize(self, tokens): return BadInstructionError() -def JUMP(x : str, line_num : int) -> int: - raise NotImplementedError() - +def JUMP(x : str, line_num : int, code: list) -> int: # search forward skip_labels = 0 - for i in range(line_num, len(self.code)): - if x+":" == self.code[i]: + for i in range(line_num, len(code)): + if x+":" == code[i]: jump_size = (i - line_num - skip_labels) * 4 # how many instructions to jump ahead return jump_size - if self.code[i][-1] == ':': + if code[i][-1] == ':': skip_labels += 1 # search backward skip_labels = 0 for i in range(line_num, -1, -1): # substruct correct label itself - if self.code[i][-1] == ':': + if code[i][-1] == ':': skip_labels += 1 - if x+":" == self.code[i]: + if x+":" == code[i]: jump_size = (i - line_num + skip_labels) * 4 # how many instructions to jump behind return jump_size diff --git a/src/riscv_assembler/parse.py b/src/riscv_assembler/parse.py index 13dd736..643bc53 100644 --- a/src/riscv_assembler/parse.py +++ b/src/riscv_assembler/parse.py @@ -1,5 +1,6 @@ from riscv_assembler.instr_arr import * from types import FunctionType as function +from os.path import exists __all__ = ['Parser'] class _Parser: @@ -18,13 +19,12 @@ class _Parser: ''' def __call__(self, *args) -> list: - if _Parser.is_file(*args): - return _Parser.interpret_file(_Parser.read_file(*args)) - return [_Parser.interpret(_Parser.tokenize(x)) for x in args[0].split("\n") if len(_Parser.tokenize(x)) > 0] - - @staticmethod - def is_file(x : str) -> bool: - return True if '.s' in x or '/' in x else False + if exists(*args): + return _Parser.interpret_arr(_Parser.read_file(*args)) + #return [_Parser.interpret(_Parser.tokenize(x)) for x in args[0].split("\n") if len(_Parser.tokenize(x)) > 0] + elif type(args[0]) == str: + return _Parser.interpret_arr(args[0].split('\n')) + return _Parser.interpret_arr(*args) ''' In read_file(), Check if the inputted line is appropriate before @@ -35,7 +35,7 @@ def valid_line(x : str, allow_colon : bool = False) -> bool: if x[0][0] == "#" or x[0][0] == "\n" or x[0][0] == "" or x[0][0] == ".": return False - if not allow_colon and x[0][-1] == ":" : + if not allow_colon and x[-1] == ":" : return False return True @@ -76,13 +76,13 @@ def read_file(file : str) -> list: file.close() return code''' with open(file) as f: - return f.readlines() + return [x.strip() for x in f.readlines() if x != '\n'] @staticmethod - def interpret_file(code : list) -> list: + def interpret_arr(code : list) -> list: int_code = [] - for line in code: - tokens = _Parser.tokenize(line) + for line_num, line in enumerate(code): + tokens = _Parser.tokenize(line, line_num, code) int_code += [_Parser.interpret(tokens) for _ in range(1) if len(tokens) != 0] return int_code @@ -91,12 +91,12 @@ def interpret_file(code : list) -> list: Tokenize a given line ''' @staticmethod - def tokenize(line : str) -> list: + def tokenize(line : str, line_num: int = None, code : list = None) -> list: line = line.strip() - if len(line) > 0 and _Parser.valid_line(line, True): + if len(line) > 0 and _Parser.valid_line(line): tokens = _Parser.handle_inline_comments(line).split() tokens = _Parser.handle_specific_instr(tokens) - return tokens + return tokens + [line_num, code] if line_num != None and code != None else tokens return [] ''' diff --git a/tests/__pycache__/test_class.cpython-38-pytest-7.2.2.pyc b/tests/__pycache__/test_class.cpython-38-pytest-7.2.2.pyc index c76ee75..fdf57f5 100644 Binary files a/tests/__pycache__/test_class.cpython-38-pytest-7.2.2.pyc and b/tests/__pycache__/test_class.cpython-38-pytest-7.2.2.pyc differ diff --git a/tests/test_class.py b/tests/test_class.py index 8829373..792d623 100644 --- a/tests/test_class.py +++ b/tests/test_class.py @@ -155,8 +155,8 @@ def test_11(): assert func11() == [] # Test file test2.s, need to implement JUMP -#def test_12(): -# assert func12() == ['0x00a00413', '0x00a00493', '0x00848263', '0xfe040493'] +def test_12(): + assert func12() == ['0x00a00413', '0x00a00493', '0x00848263', '0xfe040493'] def test_13(): assert func13() == ['0x00812023']