Skip to content

Commit

Permalink
Merge pull request #24 from hell03end/dev/fix_master
Browse files Browse the repository at this point in the history
Fix msater branch
  • Loading branch information
hell03end authored Jan 4, 2021
2 parents 3bc0a69 + d9a9ef5 commit 7f73ec2
Show file tree
Hide file tree
Showing 51 changed files with 1,178 additions and 310 deletions.
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2017 HSE University
Copyright (c) 2017 Dmitry Pchelkin (@hell03end), Alexey Ivanov (@7rick03ligh7)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
1 change: 0 additions & 1 deletion Procfile

This file was deleted.

79 changes: 10 additions & 69 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,74 +1,15 @@
FPGAMarsohodCAD
===============
CAD for automatically configuring FPGA "Marsohod"
CAD for generating base configurations for FPGA "Marsohod".

#### Requirements
* Python >= 3.6
Structure:
* `engine` - core logic of generating FPGA Quartus-compatible configurations.
* `api_client.py` - simple rest-like API.
* `cli_client.py` - simple cli client. Engine could also be used directly as python package (see `engine_example.py` form `examples` folder).
* `web_client.py` - base web interface for solution. Written with legacy bootstrap and flask. TODO: should be overwritten as SPA with API usage.

#### Examples
See `engine_example.py` and `convert_example.py`.
### Requirements
* Python >= 3.9

FPGA Marsohod CAD web interface
-------------------------------
See `prepare.sh` or `prepare.bat` for more detailed instructions for Linux/Windows.

#### How to run [linux]?
```bash
# first, clone repository
git clone https://github.com/hell03end/FPGAMarsohodCAD

# install dependencies
pip install --no-cache -r requirements.txt
pip install --no-cache -r engine/requirements.txt

# set environment variables [use 'set' instead of 'export' for winfows]
# export FLASK_APP=app.py
export STATIC_PATH=.generated # where to store generated configs

# [use '%STATIC_PATH%' for windows]
mkdir $STATIC_PATH
mkdir configs

# create database
flask db init
flask db migrate
flask db upgrade

# compile translations (optional)
flask translate compile

# finally, run application
flask run --with-threads
```

*(optional) clean project directory from previous starts*
```bash
rm -r *.db migrations logs __pycache__ $STATIC_PATH
```

You also need to create `.env` file to configure mailing.

Example:
```bash
SECRET_KEY=<secret key>
MAIL_SERVER=smtp.googlemail.com
MAIL_PORT=587
MAIL_USE_TLS=1
MAIL_USERNAME="[email protected]"
MAIL_PASSWORD=<password>
```

<!-- ```bash
# To get text run:
pybabel extract -F babel.cfg -k _l -o messages.pot .
# To add a translation run:
pybabel init -i messages.pot -d web_client/translations -l ru
# To update existing translations run:
pybabel update -i messages.pot -d web_client/translations
# To compile translations run:
pybabel compile -d web_client/translations
``` -->

Read more on **[wiki](https://github.com/hell03end/FPGAMarsohodCAD/wiki)**.

[`CHANGELOG`](https://github.com/hell03end/FPGAMarsohodCAD/wiki/Changelog)
### How to run
See `run.sh`.
21 changes: 1 addition & 20 deletions api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@

from flask import Flask, Response, jsonify, make_response, request
from flask_sslify import SSLify
from werkzeug.contrib.profiler import ProfilerMiddleware

from engine import BOARDS, FUNCTIONS, MIPS, Board
from engine.exceptions import InvalidProjectName
Expand All @@ -28,7 +27,7 @@ class AppConfig(object):
SSL_REDIRECT = True # NOTE not working in debug mode


def create_app(config: AppConfig, name: str=None) -> Flask:
def create_app(config: AppConfig, name: str = None) -> Flask:
app = Flask(name or __name__)
app.config.from_object(config)

Expand Down Expand Up @@ -225,35 +224,17 @@ def make_shell_context() -> dict:
}


def enable_profiling(app: Flask, path: str) -> NoReturn:
if not os.path.exists(path):
logging.info(f"Create '{path}'.")
os.mkdir(path)

app.config['PROFILE'] = True
logging.warning("Profiler is running!")
app.wsgi_app = ProfilerMiddleware(
app.wsgi_app,
restrictions=[30], # length
profile_dir=path
)


def parse_argv() -> Namespace:
parser = ArgumentParser(description="Starter for API client")
parser.add_argument('host', type=str, default=None, nargs="?")
parser.add_argument('--port', '-p', type=int, default=None)
parser.add_argument('--debug', '-d', action="store_true")
parser.add_argument('--profile', '-P', action="store_true")
return parser.parse_args()


def main() -> int:
args = parse_argv()

if args.profile:
enable_profiling(app, path="perf-logs")

app.run(host=args.host, port=args.port, debug=args.debug)

return 0
Expand Down
8 changes: 4 additions & 4 deletions cli_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ class ReturnCode(Enum):
class Config(object):
def __init__(self,
config: str,
project_name: str=None,
mips_type: str=None,
path: str=None) -> NoReturn:
project_name: str = None,
mips_type: str = None,
path: str = None) -> NoReturn:
self.configs = None
self.functions = None
self.functions_params = None
Expand Down Expand Up @@ -83,7 +83,7 @@ def _to_dict(items: Iterable[Any]) -> Dict[Any, bool]:
def generate_board_and_save(board_name: str,
config: Config,
path_to_save: str = None,
archive: bool=False) -> NoReturn:
archive: bool = False) -> NoReturn:
board = Board(board_name).setup(
project_name=config.project_name,
mips_type=config.mips_type,
Expand Down
13 changes: 0 additions & 13 deletions deployment/auth/readme.md

This file was deleted.

Empty file removed deployment/nginx/web_client
Empty file.
8 changes: 0 additions & 8 deletions deployment/supervisor/web_client.conf

This file was deleted.

26 changes: 0 additions & 26 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,12 @@ Project Documentation
=====================
> TODO Add documentation here.

Engine
------
Contains configuration files rendering methods.

**Usage example** can be found in `engine_example.py`.


Web client
----------
Contains project WEB interface.

Includes:
* `web_client` - main part
* `migrations` - database migrations


Tests
-----
Contains unit and functional tests for all parts of the project.


Navigation
----------

### Folders
* `drivers` - contains additional drivers for **Marsohod** boards for Altera Quartus II software
* `misc` - contains miscellaneous *Verilog* files which should be improved and added to the project in future releases
* `pin_assignments` - contains correct pin assignments for **Marsohod** and **De SoC** boards

### Archives
--------
* `articles` - usefull articles connected with *FPGA* and **Marsohod** themes
<!-- * `books` - usefull books connected with *FPGA* and **Marsohod** themes -->
* `datasheets` - official datasheets for **Marsohod** and **De SoC** boards
24 changes: 13 additions & 11 deletions engine/boards.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def as_archive(self) -> io.BytesIO:
""" Returns generated configs as archive. """
return Archiver.get_tar_io(self.configs)

def reset(self, path: str=None, mips_type: str=None) -> object:
def reset(self, path: str = None, mips_type: str = None) -> object:
"""
Reloads board configuration from static file
Expand Down Expand Up @@ -122,13 +122,13 @@ def _reset_mips(self, config_path: str, mips_type: str) -> NoReturn:
self._mips_type = mips_type

def setup(self,
project_name: str=None,
flt: dict=None,
conf: dict=None,
func: dict=None,
mips_type: str=None,
project_output_directory: str=None,
reset: bool=True) -> object:
project_name: str = None,
flt: dict = None,
conf: dict = None,
func: dict = None,
mips_type: str = None,
project_output_directory: str = None,
reset: bool = True) -> object:
"""
Setup board configuration
Expand Down Expand Up @@ -161,7 +161,7 @@ def _filter(params: dict) -> dict:
project_output_directory or self._qsf['project_output_directory']
return self

def generate(self, project_name: str=None, **kwargs) -> object:
def generate(self, project_name: str = None, **kwargs) -> object:
""" Generates FPGA configs """
if project_name or kwargs:
self.setup(project_name=project_name, **kwargs)
Expand Down Expand Up @@ -196,7 +196,7 @@ def generate(self, project_name: str=None, **kwargs) -> object:
)))
return self

def dump(self, path: str=None) -> object:
def dump(self, path: str = None) -> object:
""" Save FPGA config files to separate folder """
path = path or self.project_name
create_dirs(path, rewrite=False)
Expand Down Expand Up @@ -225,12 +225,14 @@ def save_to_file(filename: str, content: Any) -> NoReturn:
errors_count, path)
return self

def archive(self, path: str=None) -> object:
def archive(self, path: str = None) -> object:
""" Generate tar file with FPGA config files for specific project """
Archiver.to_tar_flow(self.configs, path=path or self.project_name)
return self


# TODO: handle 130 pin for Marsohod3
# BUG: incorrect clock rate (WTF??? I don't remember what does it mean)
class Board(GenericBoard):
""" Predefined board interface """

Expand Down
4 changes: 3 additions & 1 deletion engine/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class PATHS(object):
MIPS = os.path.join(STATIC, "school_mips")


# Configure output paths
class DESTINATIONS(object):
OUTPUT = "output_files"
FUNC = "functions"
Expand All @@ -28,10 +29,11 @@ class MIPS(object):
)


# native supported boards
# 'natively' supported boards
BOARDS = ("marsohod2", "marsohod2b", "marsohod3", "marsohod3b", "de1soc")


# Mappings for descriptions
class FUNCTIONS(object):
ITEMS = {
'ButtonDebouncer': "Button Debouncer: add delay between button inputs",
Expand Down
2 changes: 1 addition & 1 deletion engine/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def wrapper(*args, **kwargs) -> Any:
return wrapper


def none_safe(to_args: bool=True, to_kwargs: bool=True) -> Callable:
def none_safe(to_args: bool = True, to_kwargs: bool = True) -> Callable:
"""
Pass only not None args/kwargs to function
Doesn't handle exceptions.
Expand Down
Loading

0 comments on commit 7f73ec2

Please sign in to comment.