-
Notifications
You must be signed in to change notification settings - Fork 80
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from phoeniX-Digital-Design/phoeniX-V0.4.1
phoeniX V0.4.1
- Loading branch information
Showing
13 changed files
with
1,516 additions
and
140 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,178 @@ | ||
# AssembleX V3.0 | ||
# RISC-V Assembly Software Assistant for the phoeniX project (https://github.com/phoeniX-Digital-Design/phoeniX) | ||
|
||
# Description: AssembleX main code | ||
# Copyright 2024 Iran University of Science and Technology. <[email protected]> | ||
|
||
# Permission to use, copy, modify, and/or distribute this software for any | ||
# purpose with or without fee is hereby granted, provided that the above | ||
# copyright notice and this permission notice appear in all copies. | ||
|
||
import sys | ||
import os | ||
import glob | ||
|
||
from Software.AssembleX.variables import * | ||
from Software.AssembleX.assembler import assembler | ||
from Software.AssembleX.address_mapping import address_mapping | ||
from Software.AssembleX.address_mapping import label_mapping | ||
from Software.AssembleX.address_mapping import define_reset_address | ||
from Software.AssembleX.data_conversion import binary_to_hex | ||
from Software.AssembleX.data_conversion import ascii_to_hex | ||
|
||
testbench_file = "phoeniX_Testbench.v" | ||
option = sys.argv[1] | ||
project_name = sys.argv[2] | ||
output_name = project_name + "_firmware" + ".hex" | ||
|
||
if option == 'sample': | ||
directory = "Sample_Assembly_Codes" | ||
elif option == 'code': | ||
directory = "User_Codes" | ||
else: | ||
raise ValueError("Options are: sample, code") | ||
|
||
print("\nAssembleX V3.0 - RV32IM Assembly Code Executant Software") | ||
print("Iran University of Science and Technology - Summer 2024") | ||
print("--------------------------------------------------------") | ||
|
||
try: | ||
source_path = list(glob.iglob(os.path.join("Software", directory, project_name, '*' + ".s")))[0] | ||
firmware_hex_path = os.path.join("Software", directory, project_name, output_name) | ||
print(source_path) | ||
print(firmware_hex_path) | ||
#source_path = sys.argv[1] | ||
#firmware_hex_path = sys.argv[1].rstrip('.s') + '_firmware.hex' | ||
except: | ||
print('INFO: No arguments/unsupported arguments\n') | ||
|
||
try: | ||
source_file = open(source_path, "r") | ||
source_code_unformatted = source_file.read().splitlines() | ||
print("INFO: Source file opened successfully\n") | ||
except: | ||
print("FATAL ERROR: Unable to open source file\n") | ||
exit(1) | ||
|
||
print('Assembly code pre-processing') | ||
print('----------------------------') | ||
source_code = [] | ||
for line in source_code_unformatted: | ||
instruction_format_space = " ".join(line.split()) | ||
instruction_format_comments = " #".join(instruction_format_space.split('#', 2)) | ||
instruction_format_leadspace = instruction_format_comments.lstrip() | ||
source_code.append(instruction_format_leadspace) | ||
|
||
# Re-format immediate expressions | ||
processed_code_1 = [] | ||
for line in source_code: | ||
arguments = line.split(',') | ||
try: | ||
if arguments[0][0] == '#': | ||
processed_code_1.append(line) | ||
continue | ||
elif arguments[0] == '.RESET_ADDRESS': | ||
processed_code_1.append(line) | ||
continue | ||
except: | ||
processed_code_1.append(line) | ||
continue | ||
# Check for 2 argument immediate expressions: 'x(y)' -> parse: 'y x' | ||
# Check for ASCII: char -> hex | ||
parse_ascii = [False] | ||
try: | ||
arguement_2_wc = arguments[1] | ||
arguement_2_wc = arguement_2_wc.split('#', 2) | ||
len_arguement_2_wc = len(arguement_2_wc) | ||
arguement_2 = [arguement_2_wc[0]] | ||
ascii_to_hex(arguement_2) | ||
arguement_2_pp = arguement_2[0].replace(')', '(') | ||
arguement_2_pp = "".join(arguement_2_pp.split()) | ||
arguement_2_list = arguement_2_pp.split('(') | ||
if len_arguement_2_wc == 2: | ||
arguments[1] = ' ' + arguement_2_list[1] + ', ' + arguement_2_list[0] + ' ' + '#' + arguement_2_wc[1] # Modified expression | ||
else: # No inline comment | ||
arguments[1] = ' ' + arguement_2_list[1] + ', ' + arguement_2_list[0] # Modified expression | ||
processed_code_1.append(",".join(arguments)) | ||
except: | ||
if parse_ascii[0]: | ||
if len_arguement_2_wc == 2: | ||
arguments[1] = arguement_2[0] + ' ' + '#' + arguement_2_wc[1] # Modified expression | ||
else: | ||
arguments[1] = arguement_2[0] # Modified expression | ||
processed_code_1.append(",".join(arguments)) | ||
else: | ||
processed_code_1.append(line) | ||
continue | ||
|
||
# Remove "," change "," -> " " | ||
processed_code_2 = [] | ||
for line in processed_code_1: | ||
line = line.replace(',', ' ') | ||
processed_code_2.append(" ".join(line.split())) | ||
|
||
lines_of_code = len(processed_code_2) | ||
print('Lines of code =', lines_of_code, '\n') | ||
|
||
start_address = define_reset_address(processed_code_2[0]) | ||
|
||
for line in source_code: | ||
label_state = label_mapping(start_address, line, instruction_counter, | ||
expected_instructions_count, lable_counter, | ||
label_list, label_address_list) | ||
address_mapping(lable_counter, label_list, label_address_list) | ||
|
||
# Parser | ||
print('') | ||
print('Parser') | ||
print('------') | ||
pc[0] = start_address | ||
for line in processed_code_2: | ||
instruction_sts = assembler(pc, line, line_number, error_flag, error_counter, bin_instruction) | ||
line_number = line_number + 1 | ||
|
||
# Summary | ||
print('\nSummary') | ||
print('-------') | ||
if error_flag[0] == 0: | ||
print('- Lines of code (source) = ', lines_of_code) | ||
print('- Assembled instructions = ', instruction_counter[0]) | ||
print('- Instructions with ERRORS = ', error_counter[0]) | ||
binary_to_hex(bin_instruction, hex_instruction) | ||
try: | ||
# HEX firmware file write | ||
file = open(firmware_hex_path, "w") | ||
for line in hex_instruction: | ||
file.write(line + '\n') | ||
print('\nDONE: Successfully created FIRMWARE file\n') | ||
file.close() | ||
except: | ||
print('\nFATAL ERROR: Unable to create FIRMWARE file\n') | ||
else: | ||
print('- Lines of code (source) = ', lines_of_code) | ||
print('- Assembled instructions = ', instruction_counter[0]) | ||
print('- Instructions with ERRORS = ', error_counter[0]) | ||
print('\nFAIL:Failed to parse the assembly code due to errors') | ||
|
||
# Change firmware in the testbench file | ||
with open(testbench_file, 'r') as file: | ||
lines = file.readlines() | ||
# Edit source files of testbench names | ||
with open(testbench_file, 'w') as file: | ||
for line in lines: | ||
# Change instruction memory source file | ||
if line.startswith(" `define FIRMWARE "): | ||
print("Line found!") | ||
# Modify the input file name | ||
firmware_hex_path = firmware_hex_path.replace("\\", "\\\\") | ||
print(firmware_hex_path) | ||
modified_line = line.replace(line,' `define FIRMWARE '+ '"' + firmware_hex_path + '"' +'\n' ) | ||
print(modified_line) | ||
file.write(modified_line) | ||
else: | ||
file.write(line) | ||
|
||
# OS: cmd commands to execute Verilog simulations: | ||
os.system("iverilog -IModules -o phoeniX.vvp phoeniX_Testbench.v") | ||
os.system("vvp phoeniX.vvp") | ||
os.system("gtkwave phoeniX.gtkw") |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
![License](https://img.shields.io/github/license/phoeniX-Digital-Design/AssembleX?color=dark-green) | ||
![GCC Test](https://img.shields.io/badge/GCC_tests-passed-dark_green) | ||
![Version](https://img.shields.io/badge/Version-0.4-blue) | ||
![Version](https://img.shields.io/badge/Version-0.4.1-blue) | ||
![ISA](https://img.shields.io/badge/RV32-IEM_extension-blue) | ||
|
||
<picture> | ||
|
@@ -34,6 +34,7 @@ Publications: | |
|
||
- A. Delavari, F. Ghoreishy, H. S. Shahhoseini and S. Mirzakuchaki (2023), “phoeniX: A RISC-V Platform for Approximate Computing Technical Specifications,” [Online]. Available: http://www.iust.ac.ir/content/76158/phoeniX-POINTS--A-RISC-V-Platform-for-Approximate-Computing | ||
|
||
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. | ||
|
||
- Designed By: [Arvin Delavari](https://github.com/ArvinDelavari) and [Faraz Ghoreishy](https://github.com/FarazGhoreishy) | ||
- Contact us: [email protected] - [email protected] | ||
|
@@ -271,15 +272,14 @@ We have meticulously developed a lightweight and user-friendly software solution | |
|
||
This tool enhances the efficiency of the code execution process, offering a streamlined experience for users seeking to enter the realm of assembly programming on pheoniX processor in a very simple and user-friendly way. | ||
|
||
Before running the script, note that the assembly output of the Venus Simulator for the code must be also saved in the project directory. | ||
To run any of these sample projects simply run python `AssembleX_V1.0.py sample` followed by the name of the project passed as a variable named project to the Python script. | ||
To run any of these sample projects simply run python `AssembleX.py sample` followed by the name of the project passed as a variable named project to the Python script. | ||
The input command format for the terminal follows the structure illustrated below: | ||
```shell | ||
python AssembleX_V1.0.py sample {project_name} | ||
python AssembleX.py sample {project_name} | ||
``` | ||
For example: | ||
```shell | ||
python AssembleX_V1.0.py sample fibonacci | ||
python AssembleX.py sample fibonacci | ||
``` | ||
After execution of this script, firmware file will be generated and this final file can be directly fed to our Verilog testbench. AssembleX automatically runs the testbench and calls upon gtkwave to display the selected signals in the waveform viewer application, gtkwave. | ||
</div> | ||
|
@@ -290,7 +290,7 @@ After execution of this script, firmware file will be generated and this final f | |
In order to run your own code on phoeniX, create a directory named to your project such as `/my_project` in `/Software/User_Codes`. Put all your `user_code.s` files in my_project and run the following command from the main directory: | ||
|
||
```shell | ||
python AssembleX_V1.0.py code my_project | ||
python AssembleX.py code my_project | ||
``` | ||
|
||
Provided that you name your project sub-directory correctly the AssembleX software will create `my_project_firmware.hex` and fed it directly to the testbench of phoeniX processor. After that, iverilog and GTKWave are used to compile the design and view the selected waveforms. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
# AssembleX V3.0 | ||
# RISC-V Assembly Software Assistant for the phoeniX project (https://github.com/phoeniX-Digital-Design/phoeniX) | ||
|
||
# Description: Address mapping and translation functions | ||
# Copyright 2024 Iran University of Science and Technology. <[email protected]> | ||
|
||
# Permission to use, copy, modify, and/or distribute this software for any | ||
# purpose with or without fee is hereby granted, provided that the above | ||
# copyright notice and this permission notice appear in all copies. | ||
|
||
def define_reset_address(first_line): | ||
start_address = first_line.split() | ||
try: | ||
if start_address[0] == '.RESET_ADDRESS': | ||
address_pre = start_address[1] | ||
if address_pre[0:2] == '0x' or address_pre[0:2] == '0X': | ||
address = (int(address_pre, base=16) >> 2) * 4 | ||
else: | ||
address = (int(address_pre) >> 2) * 4 | ||
print('INFO: .RESET_ADDRESS set to', "0x{:08x}".format(address)) | ||
return address | ||
else: | ||
print('WARNING: .RESET_ADDRESS not defined. -> .RESET_ADDRESS overridden to 0x00000000\n') | ||
return 0 | ||
except: | ||
print('WARNING: .RESET_ADDRESS not defined. -> .RESET_ADDRESS overridden to 0x00000000\n') | ||
return 0 | ||
|
||
def label_mapping(base_address, line, instrcnt, expected_instructions_count, label_counter, label_list, label_address_list): | ||
words = line.split() | ||
# Check if blank line or comment or start_address | ||
try: | ||
if words[0][0] == '#': | ||
# Ignore comment and move on | ||
return 0 | ||
elif words[0] == '.RESET_ADDRESS': | ||
# Ignore start_address | ||
return 0 | ||
except: | ||
# Ignore blank line and move on | ||
return 0 | ||
|
||
if len(words) == 1 and line[-1] == ':': | ||
label = line.split(':')[0] | ||
label_counter[0] = label_counter[0] + 1 | ||
label_list.append(label) | ||
label_address_list.append(base_address + int(expected_instructions_count[0]) * 4) | ||
elif len(words) > 1 and words[0][-1] == ':' and words[1][0] == '#': # Decodes labels with comments | ||
label = line.split(':')[0] | ||
label_counter[0] = label_counter[0] + 1 | ||
label_list.append(label) | ||
label_address_list.append(base_address + int(expected_instructions_count[0]) * 4) | ||
else: | ||
# It is an instruction | ||
instrcnt[0] = instrcnt[0] + 1 | ||
if words[0] == 'LI' or words[0] == 'li' or words[0] == 'LA' or words[0] == 'la': | ||
offset = 2 # Because LI = expands to two instructions | ||
else: | ||
offset = 1 | ||
expected_instructions_count[0] = expected_instructions_count[0] + offset | ||
|
||
def address_mapping(label_counter, label_list, label_address_list): | ||
print('Address Mapping') | ||
print('---------------') | ||
for i in range(label_counter[0]): | ||
print('%+-8s' % label_list[i], ": 0x{:08x}".format(label_address_list[i])) |
Oops, something went wrong.