Skip to content

Commit

Permalink
Initial commit, moving from old repo
Browse files Browse the repository at this point in the history
  • Loading branch information
kcelebi committed Apr 11, 2023
0 parents commit 282e4fa
Show file tree
Hide file tree
Showing 33 changed files with 3,109 additions and 0 deletions.
49 changes: 49 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Use the latest 2.1 version of CircleCI pipeline process engine.
# See: https://circleci.com/docs/2.0/configuration-reference
version: 2.1

# Orbs are reusable packages of CircleCI configuration that you may share across projects, enabling you to create encapsulated, parameterized commands, jobs, and executors that can be used across multiple projects.
# See: https://circleci.com/docs/2.0/orb-intro/
orbs:
# The python orb contains a set of prepackaged CircleCI configuration you can use repeatedly in your configuration files
# Orb commands and jobs help you with common scripting around a language/tool
# so you dont have to copy and paste it everywhere.
# See the orb documentation here: https://circleci.com/developer/orbs/orb/circleci/python
python: circleci/python@1.5.0

# Define a job to be invoked later in a workflow.
# See: https://circleci.com/docs/2.0/configuration-reference/#jobs
jobs:
build-and-test: # This is the name of the job, feel free to change it to better match what you're trying to do!
# These next lines defines a Docker executors: https://circleci.com/docs/2.0/executor-types/
# You can specify an image from Dockerhub or use one of the convenience images from CircleCI's Developer Hub
# A list of available CircleCI Docker convenience images are available here: https://circleci.com/developer/images/image/cimg/python
# The executor is the environment in which the steps below will be executed - below will use a python 3.10.2 container
# Change the version below to your required version of python
docker:
- image: cimg/python:3.10.2
# Checkout the code as the first step. This is a dedicated CircleCI step.
# The python orb's install-packages step will install the dependencies from a Pipfile via Pipenv by default.
# Here we're making sure we use just use the system-wide pip. By default it uses the project root's requirements.txt.
# Then run your tests!
# CircleCI will report the results back to your VCS provider.
steps:
- checkout
- python/install-packages:
pkg-manager: pip
# app-dir: ~/project/package-directory/ # If you're requirements.txt isn't in the root directory.
# pip-dependency-file: test-requirements.txt # if you have a different name for your requirements file, maybe one that combines your runtime and test requirements.
- run:
name: Run tests
# This assumes pytest is installed via the install-package step above
#command: python -m tests.test_class
command: pytest


# Invoke jobs via workflows
# See: https://circleci.com/docs/2.0/configuration-reference/#workflows
workflows:
sample: # This is the name of the workflow, feel free to change it to better match your workflow.
# Inside the workflow, you define the jobs you want to run.
jobs:
- build-and-test
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
old.md
riscv_assembler/prjtest.pybuild
dist
riscv_assembler.egg-info
build
.pytest_cache/
deprc_setup.py
__pycache__/
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 Kaya Celebi

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
[![kcelebi](https://circleci.com/gh/kcelebi/riscv-assembler.svg?style=svg)](https://circleci.com/gh/kcelebi/riscv-assembler)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

![example](references/mdimg.png)
# riscv-assembler Documentation
RISC-V Assembly code assembler package. [View the full documentation here](https://www.riscvassembler.org)

This package contains tools and functions that can convert **RISC-V Assembly code to machine code**. The whole process is implemented using Python purely for understandability, less so for efficiency in computation. These tools can be used to **convert given lines of code or [whole files](#convert) to machine code**. For conversion, output file types are binary, text files, and printing to console. The supported instruction types are **R, I, S, SB, U, and UJ**. Almost all standard instructions are supported, most pseudo instructions are also supported.

Feel free to open an issue or contact me at [kayacelebi17@gmail.com](mailto:kayacelebi17@gmail.com?subject=[GitHub]%20riscv-assembler) with any questions/inquiries.

# Installation
The package can be installed using pip:

$ pip install riscv-assembler

If issues arise try:

$ python3 -m pip install riscv-assembler

It's possible tha the ``bitstring`` dependency might not install correctly. If this occurs, you can simply pip install it separately:

$ pip install bitstring
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[build-system]
requires = ["setuptools>=45", "setuptools_scm[toml]>=6.2"]
build-backend = "setuptools.build_meta"

[tool.setuptools_scm]
2 changes: 2 additions & 0 deletions pytest.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[pytest]
pythonpath = . src
Binary file added references/mdimg.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pytest==7.2.2
33 changes: 33 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
[metadata]
name = riscv-assembler
author = Kaya Celebi
author_email = kayacelebi17@gmail.com
description = RISC-V Assembly code assembler package for Python.
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/kcelebi/riscv-assembler
project_urls =
Bug Tracker = https://github.com/kcelebi/riscv-assembler/issues
Changelog = https://github.com/kcelebi/riscv-assembler/releases
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
Intended Audience :: Developers

[options]
package_dir =
= src
packages = find:
python_requires = >=3.6
install_requires =
bitstring

[options.packages.find]
where = src

[options.package_data]
* = data/*.dat

[options.entry_points]
console_scripts =
riscv_assembler = riscv_assembler.app:entry_point
Empty file added src/riscv_assembler/__init__.py
Empty file.
164 changes: 164 additions & 0 deletions src/riscv_assembler/convert.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
'''
Current Functionality:
- Read given file
- Tokenize that file, split up variables on each line
- Identify function, registers, variables
- Convert tokens of that line to machine code
- Output to text, bin, or console
Immediate ToDos:
- Implement hexmode
- Go through and fix the instruction conversions themselves
- Update tests
'''

from riscv_assembler.instr_arr import *
from riscv_assembler.parse import *

__all__ = ['AssemblyConverter']

class AssemblyConverter:

def __init__(self, output_mode : str = 'a', nibble_mode : bool = False, hex_mode : bool = False) -> None:
self.__output_mode = self.__check_output_mode(output_mode)
self.__nibble_mode = self.__check_nibble_mode(nibble_mode)
self.__hex_mode = self.__check_hex_mode(hex_mode)

def __str__(self):
return "Output: {output_mode}, Nibble: {nibble_mode}, Hex: {hex_mode}".format(
output_mode = self.__output_mode,
nibble_mode = self.__nibble_mode,
hex_mode = self.__hex_mode
)

def __repr__(self):
return "Output: {output_mode}, Nibble: {nibble_mode}, Hex: {hex_mode}".format(
output_mode = self.__output_mode,
nibble_mode = self.__nibble_mode,
hex_mode = self.__hex_mode
)

def clone(self):
return AssemblyConverter(
output_mode = self.__output_mode,
nibble_mode = self.__nibble_mode,
hex_mode = self.__hex_mode
)

def __call__(self, *args):
return self.convert(*args)

def __check_output_mode(self, x) -> str:
mod = ''.join(sorted(x.split()))
assert mod in ['a', 'f', 'p', None], "Output Mode needs to be one of a(rray), f(ile), p(rint), or None."
return x

def __check_nibble_mode(self, x) -> str:
assert type(x) == bool, "Nibble mode needs to be a boolean."
return x

def __check_hex_mode(self, x) -> str:
assert type(x) == bool, "Hex mode needs to be a boolean."
return x

'''
Property: the way to output machine code
Options: 'a', 'f', 'p'
'''
@property
def output_mode(self) -> str:
return self.__output_mode

@output_mode.setter
def output_mode(self, x : str) -> None:
self.__output_mode = x

'''
Property: whether to print in nibbles (only applicable for text or print)
True = nibble
False = full number
'''
@property
def nibble_mode(self) -> str:
return self.__nibble_mode

@nibble_mode.setter
def nibble_mode(self, x : str) -> None:
self.__nibble_mode = x

'''
Property: whether to return as hex or not
True = hex
False = binary
'''
@property
def hex_mode(self) -> str:
return self.__hex_mode

@hex_mode.setter
def hex_mode(self, x : str) -> None:
self.__hex_mode = x

'''
Put it all together. Need to modify for output type.
Input is either a file name or string of assembly.
'''
def convert(self, input : str, file : str = None):
output = Parser(input)
assert len(output) > 0, "Provided input yielded nothing from parser. Check input."
output = self.mod(output) # apply nibble mode, hex mode

if self.__output_mode == 'a':
return output
elif self.__output_mode == 'f':
assert file != None, "For output mode to file, need to provided file name."
AssemblyConverter.write_to_file(output, file)
return
elif self.__output_mode == 'p':
print('\n'.join(output))
return

raise NotImplementedError()

@staticmethod
def write_to_file(output : list, file : str) -> None:
extension = file[-4:]

if extension == '.bin':
with open(file, 'wb') as f:
for instr in output:
byte_array = [instr[i:i+8] for i in range(0,len(instr),8)]
byte_list = [int(b,2) for b in byte_array]
f.write(bytearray(byte_list))
return

elif extension == '.txt':
with open(file, 'w') as f:
for instr in output:
f.write(instr + "\n")

return

elif extension == '.csv':
raise NotImplementedError()

elif extension == '.dat':
raise NotImplementedError()

raise NotImplementedError()

def mod(self, output : list) -> list:
if self.__nibble_mode:
output = AssemblyConverter.apply_nibble(output)
elif self.__hex_mode:
output = AssemblyConverter.apply_hex(output)
return output

@staticmethod
def apply_nibble(output : list) -> list:
return ['\t'.join([elem[i:i+4] for i in range(0, len(elem), 4)]) for elem in output]

@staticmethod
def apply_hex(output : list) -> list:
return ['0x' + '{:08X}'.format(int(elem, 2)).lower() for elem in output]
67 changes: 67 additions & 0 deletions src/riscv_assembler/data/instr_data.dat
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
add 0110011 000 0000000
sub 0110011 000 0100000
sll 0110011 001 0000000
slt 0110011 010 0000000
sltu 0110011 011 0000000
xor 0110011 100 0000000
srl 0110011 101 0000000
sra 0110011 101 0100000
or 0110011 110 0000000
and 0110011 111 0000000
addw 0111011 000 0000000
subw 0111011 000 0100000
sllw 0111011 001 0000000
slrw 0111011 101 0000000
sraw 0111011 101 0100000
addi 0010011 000
lb 0000011 000
lh 0000011 001
lw 0000011 010
ld 0000011 011
lbu 0000011 100
lhu 0000011 101
lwu 0000011 110
fence 0001111 000
fence.i 0001111 001
slli 0010011 001 0000000
slti 0010011 010
sltiu 0010011 011
xori 0010011 100
slri 0010011 101 0000000
srai 0010011 101 0100000
ori 0010011 110
andi 0010011 111
addiw 0011011 000
slliw 0011011 001 0000000
srliw 0011011 101 0000000
sraiw 0011011 101 0100000
jalr 1100111 000
ecall 1110011 000 000000000000
ebreak 1110011 000 000000000001
CSRRW 1110011 001
CSRRS 1110011 010
CSRRC 1110011 011
CSRRWI 1110011 101
CSRRSI 1110011 110
CSRRCI 1110011 111
sw 0100011 010 -1
sb 0100011 000 -1
sh 0100011 001 -1
sd 0100011 011 -1
beq 1100011 000 -1
bne 1100011 001 -1
blt 1100011 100 -1
bge 1100011 101 -1
bltu 1100011 110 -1
bgeu 1100011 111 -1
auipc 0010111 -1 -1
lui 0110111 -1 -1
jal 1101111 -1 -1
mul 0110011 000 0000001
mulh 0110011 001 0000001
mulsu 0110011 010 0000001
mulu 0110011 011 0000001
div 0110011 100 0000001
divu 0110011 101 0000001
rem 0110011 110 0000001
remu 0110011 111 0000001
Loading

0 comments on commit 282e4fa

Please sign in to comment.