diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..473e0e348315eb4b4cc98afc4e9a60832546e0e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,30 @@ +.vs/ +.vscode/ +build*/ +bin*/ +logs/ +dist/ +CMakeLists.txt.user* +*.autosave +*.creator +*.creator.user* +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* +*~ +.fuse_hudden* +.directory +.Trash-* +.nfs* +Thumbs.db +Thumbs.db:encryptable +ehthumbs.db +ehthumbs_vista.db +$RECYCLE.BIN/ +*.stackdump +[Dd]esktop.ini +*.egg-info \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 2130f26d6be5ccf8185aebd9f03003645cb9c2f8..0000000000000000000000000000000000000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,10 +0,0 @@ -stages: - - build - -PythonBuild: - stage: build - artifacts: - untracked: true - script: - - apt-get update && apt-get install python3 -y - - python3 helloworld.py \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7f6908ed2d0a352aed1e16f936a8a1d5593cccd4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,77 @@ +cmake_minimum_required(VERSION 3.8) + +project( + "B-ASIC" + VERSION 0.0.1 + DESCRIPTION "Better ASIC Toolbox for python3" + LANGUAGES C CXX +) + +find_package(fmt 6.1.2 REQUIRED) +find_package(pybind11 CONFIG REQUIRED) + +set(LIBRARY_NAME "b_asic") +set(TARGET_NAME "_${LIBRARY_NAME}") +if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY) + include(GNUInstallDirs) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_INSTALL_LIBDIR}") +endif() + +add_library( + "${TARGET_NAME}" MODULE + "${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp" +) +add_library( + "${TARGET_NAME}:${TARGET_NAME}" + ALIAS "${TARGET_NAME}" +) + +set_target_properties( + "${TARGET_NAME}" + PROPERTIES + PREFIX "" +) + +target_include_directories( + "${TARGET_NAME}" + PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/src" +) + +target_compile_features( + "${TARGET_NAME}" + PRIVATE + cxx_std_17 +) +target_compile_options( + "${TARGET_NAME}" + PRIVATE + $<$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>>: + -W -Wall -Wextra -Werror -Wno-psabi -fvisibility=hidden + $<$<CONFIG:Debug>:-g> + $<$<NOT:$<CONFIG:Debug>>:-O3> + > + $<$<CXX_COMPILER_ID:MSVC>: + /W3 /WX /permissive- /utf-8 + $<$<CONFIG:Debug>:/Od> + $<$<NOT:$<CONFIG:Debug>>:/Ot> + > +) + +target_link_libraries( + "${TARGET_NAME}" + PRIVATE + fmt::fmt-header-only + pybind11::module +) + +add_custom_target( + copy_python_files ALL + COMMAND ${CMAKE_COMMAND} -E copy_directory "${CMAKE_CURRENT_LIST_DIR}/${LIBRARY_NAME}" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${LIBRARY_NAME}" + COMMENT "Copying python files to ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/${LIBRARY_NAME}" +) +add_custom_target( + copy_misc_files ALL + COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_LIST_DIR}/README.md" "${CMAKE_CURRENT_LIST_DIR}/LICENSE" "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" + COMMENT "Copying misc. files to ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}" +) \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000000000000000000000000000000000000..ce996f6c4ffcc6a70d095c24ed296ec3b69e5f43 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,4 @@ +include README.md +include LICENSE +include CMakeLists.txt +recursive-include src *.cpp *.h diff --git a/README.md b/README.md index f126999b47d9a015add1400c4ec887e1c8e0a9e7..4917b55e937ac4e1a158f78ecce77e63d7e60cac 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,91 @@ -<img src="https://files.slack.com/files-pri/TSHPRJY83-FTTRW9MQ8/b-asic-logo-opaque.png" width="318" height="100"> -<br> -<h3>The leading company in circuit design<h3> \ No newline at end of file +<img src="logo.png" width="278" height="100"> + +# B-ASIC - Better ASIC Toolbox +B-ASIC is an ASIC toolbox for Python 3 that simplifies circuit design and optimization. + +## Prerequisites +The following packages are required in order to build the library: +* cmake 3.8+ + * gcc 7+/clang 7+/msvc 16+ + * fmtlib 6.1.2+ + * pybind11 2.3.0+ +* python 3.6+ + * setuptools + * wheel + * pybind11 + +## Development +How to build and debug the library during development. + +### Using CMake directly +How to build using CMake. + +#### Configuring +In `B-ASIC`: +``` +mkdir build +cd build +cmake .. +``` + +#### Building (Debug) +In `B-ASIC/build`: +``` +cmake --build . +``` +The output gets written to `B-ASIC/build/lib`. + +#### Building (Release) +In `B-ASIC/build`: +``` +cmake --build . --config Release +``` +The output gets written to `B-ASIC/build/lib`. + +### Using setuptools to create a package +How to create a package using setuptools. + +#### Setup (Binary distribution) +In `B-ASIC`: +``` +python3 setup.py bdist_wheel +``` +The output gets written to `B-ASIC/dist`. + +#### Setup (Source distribution) +In `B-ASIC`: +``` +python3 setup.py sdist +``` +The output gets written to `B-ASIC/dist`. + +#### Installation (Binary distribution) +In `B-ASIC`: +``` +python3 -m pip install b_asic-<version>-<cpver>-<cpver>_<arch>.whl +``` + +#### Installation (Source distribution) +In `B-ASIC`: +``` +python3 -m pip install b-asic-<version>.tar.gz +``` + +## Usage +How to build and use the library as a user. + +### Installation +``` +python3 -m pip install b_asic +``` + +### Importing +``` +python3 +>>> import b_asic as asic +>>> help(asic) +``` + +## License +B-ASIC is distributed under the MIT license. +See the included LICENSE file for more information. \ No newline at end of file diff --git a/b_asic/__init__.py b/b_asic/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..8bbc17ab50204e26db7dcaf0569cbfe316b3dc3a --- /dev/null +++ b/b_asic/__init__.py @@ -0,0 +1,13 @@ +""" +Better ASIC Toolbox. +TODO: More info. +""" +from _b_asic import * +from b_asic.operation import * +from b_asic.ops import * +from b_asic.pc import * +from b_asic.port import * +from b_asic.schema import * +from b_asic.sfg import * +from b_asic.signal import * +from b_asic.simulation import * \ No newline at end of file diff --git a/b_asic/operation.py b/b_asic/operation.py new file mode 100644 index 0000000000000000000000000000000000000000..4bea5047775df99993f9bf2dedfdd1fb4209834b --- /dev/null +++ b/b_asic/operation.py @@ -0,0 +1,210 @@ +""" +B-ASIC Operation Module. +TODO: More info. +""" +from b_asic.port import InputPort, OutputPort +from b_asic.signal import SignalSource, SignalDestination +from b_asic.simulation import SimulationState, OperationState +from abc import ABC, abstractmethod +from numbers import Number +from typing import NewType, List, Dict, Optional, final + +OperationId = NewType("OperationId", int) + +class Operation(ABC): + """ + Operation interface. + TODO: More info. + """ + + @abstractmethod + def identifier(self) -> OperationId: + """ + Get the unique identifier. + """ + pass + + @abstractmethod + def inputs(self) -> List[InputPort]: + """ + Get a list of all input ports. + """ + pass + + @abstractmethod + def outputs(self) -> List[OutputPort]: + """ + Get a list of all output ports. + """ + pass + + @abstractmethod + def input_count(self) -> int: + """ + Get the number of input ports. + """ + pass + + @abstractmethod + def output_count(self) -> int: + """ + Get the number of output ports. + """ + pass + + @abstractmethod + def input(self, i: int) -> InputPort: + """ + Get the input port at index i. + """ + pass + + @abstractmethod + def output(self, i: int) -> OutputPort: + """ + Get the output port at index i. + """ + pass + + @abstractmethod + def params(self) -> Dict[str, Optional[Any]]: + """ + Get a dictionary of all parameter values. + """ + pass + + @abstractmethod + def param(self, name: str) -> Optional[Any]: + """ + Get the value of a parameter. + Returns None if the parameter is not defined. + """ + pass + + @abstractmethod + def set_param(self, name: str, value: Any) -> None: + """ + Set the value of a parameter. + The parameter must be defined. + """ + pass + + @abstractmethod + def evaluate_outputs(self, state: SimulationState) -> List[Number]: + """ + Simulate the circuit until its iteration count matches that of the simulation state, + then return the resulting output vector. + """ + pass + + @abstractmethod + def split(self) -> List[Operation]: + """ + Split the operation into multiple operations. + If splitting is not possible, this may return a list containing only the operation itself. + """ + pass + + # TODO: More stuff. + +class BasicOperation(ABC, Operation): + """ + Generic abstract operation class which most implementations will derive from. + TODO: More info. + """ + + _identifier: OperationId + _input_ports: List[InputPort] + _output_ports: List[OutputPort] + _parameters: Dict[str, Optional[Any]] + + def __init__(self, identifier: OperationId): + """ + Construct a BasicOperation. + """ + self._identifier = identifier + self._input_ports = [] + self._output_ports = [] + self._parameters = {} + + @abstractmethod + def evaluate(self, inputs: list) -> list: + """ + Evaluate the operation and generate a list of output values given a list of input values. + """ + pass + + @final + def id(self) -> OperationId: + return self._identifier + + @final + def inputs(self) -> List[InputPort]: + return self._input_ports.copy() + + @final + def outputs(self) -> List[OutputPort]: + return self._output_ports.copy() + + @final + def input_count(self) -> int: + return len(self._input_ports) + + @final + def output_count(self) -> int: + return len(self._output_ports) + + @final + def input(self, i: int) -> InputPort: + return self._input_ports[i] + + @final + def output(self, i: int) -> OutputPort: + return self._output_ports[i] + + @final + def params(self) -> Dict[str, Optional[Any]]: + return self._parameters.copy() + + @final + def param(self, name: str) -> Optional[Any]: + return self._parameters.get(name) + + @final + def set_param(self, name: str, value: Any) -> None: + assert name in self._parameters # TODO: Error message. + self._parameters[name] = value + + def evaluate_outputs(self, state: SimulationState) -> List[Number]: + # TODO: Check implementation. + input_count: int = self.input_count() + output_count: int = self.output_count() + assert input_count == len(self._input_ports) # TODO: Error message. + assert output_count == len(self._output_ports) # TODO: Error message. + + self_state: OperationState = state.operation_states[self.identifier()] + + while self_state.iteration < state.iteration: + input_values: List[Number] = [0] * input_count + for i in range(input_count): + source: SignalSource = self._input_ports[i].signal().source + input_values[i] = source.operation.evaluate_outputs(state)[source.port_index] + + self_state.output_values = self.evaluate(input_values) + assert len(self_state.output_values) == output_count # TODO: Error message. + self_state.iteration += 1 + for i in range(output_count): + for signal in self._output_ports[i].signals(): + destination: SignalDestination = signal.destination + destination.evaluate_outputs(state) + + return self_state.output_values + + def split(self) -> List[Operation]: + # TODO: Check implementation. + results = self.evaluate(self._input_ports) + if all(isinstance(e, Operation) for e in results): + return results + return [self] + + # TODO: More stuff. \ No newline at end of file diff --git a/b_asic/ops.py b/b_asic/ops.py new file mode 100644 index 0000000000000000000000000000000000000000..6b3707254e8faceed0727da1ff93b9ad2582c35a --- /dev/null +++ b/b_asic/ops.py @@ -0,0 +1,75 @@ +""" +B-ASIC Core Operations Module. +TODO: More info. +""" + +from b_asic.operation import OperationId, Operation, BasicOperation +from numbers import Number +from typing import final + +class Input(Operation): + """ + Input operation. + TODO: More info. + """ + + # TODO: Implement. + pass + +class Constant(BasicOperation): + """ + Constant value operation. + TODO: More info. + """ + + def __init__(self, identifier: OperationId, value: Number): + """ + Construct a Constant. + """ + super().__init__(identifier) + self._output_ports = [OutputPort()] # TODO: Generate appropriate ID for ports. + self._parameters["value"] = value + + @final + def evaluate(self, inputs: list) -> list: + return [self.param("value")] + +class Addition(BasicOperation): + """ + Binary addition operation. + TODO: More info. + """ + + def __init__(self, identifier: OperationId): + """ + Construct an Addition. + """ + super().__init__(identifier) + self._input_ports = [InputPort(), InputPort()] # TODO: Generate appropriate ID for ports. + self._output_ports = [OutputPort()] # TODO: Generate appropriate ID for ports. + + @final + def evaluate(self, inputs: list) -> list: + return [inputs[0] + inputs[1]] + + +class ConstantMultiplication(BasicOperation): + """ + Unary constant multiplication operation. + TODO: More info. + """ + + def __init__(self, identifier: OperationId, coefficient: Number): + """ + Construct a ConstantMultiplication. + """ + super().__init__(identifier) + self._input_ports = [InputPort()] # TODO: Generate appropriate ID for ports. + self._output_ports = [OutputPort()] # TODO: Generate appropriate ID for ports. + self._parameters["coefficient"] = coefficient + + @final + def evaluate(self, inputs: list) -> list: + return [inputs[0] * self.param("coefficient")] + +# TODO: More operations. \ No newline at end of file diff --git a/b_asic/pc.py b/b_asic/pc.py new file mode 100644 index 0000000000000000000000000000000000000000..cc18d6af1dea2843257d53f9b3008d1decde3604 --- /dev/null +++ b/b_asic/pc.py @@ -0,0 +1,24 @@ +""" +B-ASIC Precedence Chart Module. +TODO: More info. +""" + +from b_asic.sfg import SFG + +class PrecedenceChart: + """ + Precedence chart constructed from a signal flow graph. + TODO: More info. + """ + + sfg: SFG + # TODO: More members. + + def __init__(self, sfg: SFG): + """ + Construct a PrecedenceChart. + """ + self.sfg = sfg + # TODO: Implement. + + # TODO: More stuff. \ No newline at end of file diff --git a/b_asic/port.py b/b_asic/port.py new file mode 100644 index 0000000000000000000000000000000000000000..6b1e8d2025ee5696f1365b8b8b2195167620925f --- /dev/null +++ b/b_asic/port.py @@ -0,0 +1,147 @@ +""" +B-ASIC Port Module. +TODO: More info. +""" + +from b_asic.signal import Signal +from abc import ABC, abstractmethod +from typing import NewType, Optional, List, Dict, final + +PortId = NewType("PortId", int) + +class Port(ABC): + """ + Abstract port class. + TODO: More info. + """ + + _identifier: PortId + + def __init__(self, identifier: PortId): + """ + Construct a Port. + """ + self._identifier = identifier + + @final + def identifier(self) -> PortId: + """ + Get the unique identifier. + """ + return self._identifier + + @abstractmethod + def signals(self) -> List[Signal]: + """ + Get a list of all connected signals. + """ + pass + + @abstractmethod + def signal_count(self) -> int: + """ + Get the number of connected signals. + """ + pass + + @abstractmethod + def signal(self, i: int = 0) -> Signal: + """ + Get the connected signal at index i. + """ + pass + + @abstractmethod + def connect(self, signal: Signal) -> None: + """ + Connect a signal. + """ + pass + + @abstractmethod + def disconnect(self, i: int = 0) -> None: + """ + Disconnect a signal. + """ + pass + + # TODO: More stuff. + +class InputPort(Port): + """ + Input port. + TODO: More info. + """ + _source_signal: Optional[Signal] + + def __init__(self, identifier: PortId): + """ + Construct an InputPort. + """ + super().__init__(identifier) + self._source_signal = None + + @final + def signals(self) -> List[Signal]: + return [] if self._source_signal == None else [self._source_signal] + + @final + def signal_count(self) -> int: + return 0 if self._source_signal == None else 1 + + @final + def signal(self, i: int = 0) -> Signal: + assert i >= 0 and i < self.signal_count() # TODO: Error message. + assert self._source_signal != None # TODO: Error message. + return self._source_signal + + @final + def connect(self, signal: Signal) -> None: + self._source_signal = signal + + @final + def disconnect(self, i: int = 0) -> None: + assert i >= 0 and i < self.signal_count() # TODO: Error message. + self._source_signal = None + + # TODO: More stuff. + +class OutputPort(Port): + """ + Output port. + TODO: More info. + """ + + _destination_signals: List[Signal] + + def __init__(self, identifier: PortId): + """ + Construct an OutputPort. + """ + super().__init__(identifier) + self._destination_signals = [] + + @final + def signals(self) -> List[Signal]: + return self._destination_signals.copy() + + @final + def signal_count(self) -> int: + return len(self._destination_signals) + + @final + def signal(self, i: int = 0) -> Signal: + assert i >= 0 and i < self.signal_count() # TODO: Error message. + return self._destination_signals[i] + + @final + def connect(self, signal: Signal) -> None: + assert signal not in self._destination_signals # TODO: Error message. + self._destination_signals.append(signal) + + @final + def disconnect(self, i: int = 0) -> None: + assert i >= 0 and i < self.signal_count() # TODO: Error message. + del self._destination_signals[i] + + # TODO: More stuff. \ No newline at end of file diff --git a/b_asic/schema.py b/b_asic/schema.py new file mode 100644 index 0000000000000000000000000000000000000000..a7642f49fcca42459b5ee04f069781e13605f517 --- /dev/null +++ b/b_asic/schema.py @@ -0,0 +1,24 @@ +""" +B-ASIC Schema Module. +TODO: More info. +""" + +from b_asic.pc import PrecedenceChart + +class Schema: + """ + Schema constructed from a precedence chart. + TODO: More info. + """ + + pc: PrecedenceChart + # TODO: More members. + + def __init__(self, pc: PrecedenceChart): + """ + Construct a Schema. + """ + self.pc = pc + # TODO: Implement. + + # TODO: More stuff. \ No newline at end of file diff --git a/b_asic/sfg.py b/b_asic/sfg.py new file mode 100644 index 0000000000000000000000000000000000000000..d39cc5245131f9815c8e495f1e9faebc024a190f --- /dev/null +++ b/b_asic/sfg.py @@ -0,0 +1,37 @@ +""" +B-ASIC Signal Flow Graph Module. +TODO: More info. +""" + +from b_asic.operation import OperationId, Operation, BasicOperation +from b_asic.signal import SignalSource, SignalDestination +from b_asic.simulation import SimulationState, OperationState +from typing import List, final + +class SFG(BasicOperation): + """ + Signal flow graph. + TODO: More info. + """ + + _operations: List[Operation] + + def __init__(self, identifier: OperationId, input_destinations: List[SignalDestination], output_sources: List[SignalSource]): + """ + Construct a SFG. + """ + super().__init__(identifier) + # TODO: Allocate input/output ports with appropriate IDs. + self._operations = [] + # TODO: Traverse the graph between the inputs/outputs and add to self._operations. + # TODO: Connect ports with signals with appropriate IDs. + + @final + def evaluate(self, inputs: list) -> list: + return [] # TODO: Implement + + @final + def split(self) -> List[Operation]: + return self._operations + + # TODO: More stuff. \ No newline at end of file diff --git a/b_asic/signal.py b/b_asic/signal.py new file mode 100644 index 0000000000000000000000000000000000000000..36be9f58d6a9a9403fb034140c3b60958f436f85 --- /dev/null +++ b/b_asic/signal.py @@ -0,0 +1,68 @@ +""" +B-ASIC Signal Module. +TODO: More info. +""" + +from b_asic.operation import Operation +from typing import NewType + +SignalId = NewType("SignalId", int) + +class SignalSource: + """ + Handle to a signal source. + TODO: More info. + """ + operation: Operation + port_index: int + + def __init__(self, operation: Operation, port_index: int): + """ + Construct a SignalSource. + """ + self.operation = operation + self.port_index = port_index + + # TODO: More stuff. + +class SignalDestination: + """ + Handle to a signal destination. + TODO: More info. + """ + operation: Operation + port_index: int + + def __init__(self, operation: Operation, port_index: int): + """ + Construct a SignalDestination. + """ + self.operation = operation + self.port_index = port_index + + # TODO: More stuff. + +class Signal: + """ + A connection between two operations consisting of a source and destination handle. + TODO: More info. + """ + _identifier: SignalId + source: SignalSource + destination: SignalDestination + + def __init__(self, identifier: SignalId, source: SignalSource, destination: SignalDestination): + """ + Construct a Signal. + """ + self._identifier = identifier + self.source = source + self.destination = destination + + def identifier(self) -> SignalId: + """ + Get the unique identifier. + """ + return self._identifier + + # TODO: More stuff. \ No newline at end of file diff --git a/b_asic/simulation.py b/b_asic/simulation.py new file mode 100644 index 0000000000000000000000000000000000000000..aa33cb337d913bead6a7446ce093efdb86b09cb5 --- /dev/null +++ b/b_asic/simulation.py @@ -0,0 +1,42 @@ +""" +B-ASIC Simulation Module. +TODO: More info. +""" + +from b_asic.operation import OperationId +from numbers import Number +from typing import List, Dict + +class OperationState: + """ + Simulation state of an operation. + TODO: More info. + """ + + output_values: List[Number] + iteration: int + + def __init__(self): + """ + Construct an OperationState. + """ + self.output_values = [] + self.iteration = 0 + +class SimulationState: + """ + Simulation state. + TODO: More info. + """ + + operation_states: Dict[OperationId, OperationState] + iteration: int + + def __init__(self): + """ + Construct a SimulationState. + """ + self.operation_states = {} + self.iteration = 0 + + # TODO: More stuff. \ No newline at end of file diff --git a/helloworld.py b/helloworld.py deleted file mode 100644 index 6d95fe97a12449aa7e3cf570dea13203d07571b9..0000000000000000000000000000000000000000 --- a/helloworld.py +++ /dev/null @@ -1 +0,0 @@ -print("Hello world") \ No newline at end of file diff --git a/logo.png b/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b1bd78fe7eb8a737ac8153576078d61492c2e9a3 Binary files /dev/null and b/logo.png differ diff --git a/setup.py b/setup.py new file mode 100644 index 0000000000000000000000000000000000000000..aa6d7a6c41247b4a4151d27d2e221c6d328851c6 --- /dev/null +++ b/setup.py @@ -0,0 +1,75 @@ +import os +import sys +import shutil +import subprocess +import setuptools +from setuptools import Extension +from setuptools.command.build_ext import build_ext + +CMAKE_EXE = os.environ.get('CMAKE_EXE', shutil.which('cmake')) + +class CMakeExtension(Extension): + def __init__(self, name, sourcedir = ""): + super().__init__(name, sources=[]) + self.sourcedir = os.path.abspath(sourcedir) + +class CMakeBuild(build_ext): + def build_extension(self, ext): + if not isinstance(ext, CMakeExtension): + return super().build_extension(ext) + + if not CMAKE_EXE: + raise RuntimeError(f"Cannot build extension {ext.name}: CMake executable not found! Set the CMAKE_EXE environment variable or update your path.") + + cmake_build_type = "Debug" if self.debug else "Release" + cmake_output_dir = os.path.abspath(os.path.dirname(self.get_ext_fullpath(ext.name))) + cmake_configure_argv = [ + CMAKE_EXE, ext.sourcedir, + "-DCMAKE_BUILD_TYPE=" + cmake_build_type, + "-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=" + cmake_output_dir, + "-DPYTHON_EXECUTABLE=" + sys.executable, + ] + cmake_build_argv = [ + CMAKE_EXE, "--build", ".", + "--config", cmake_build_type + ] + + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) + + env = os.environ.copy() + + print(f"=== Configuring {ext.name} ===") + print(f"Temp dir: {self.build_temp}") + print(f"Output dir: {cmake_output_dir}") + subprocess.check_call(cmake_configure_argv, cwd=self.build_temp, env=env) + + print(f"=== Building {ext.name} ===") + print(f"Temp dir: {self.build_temp}") + print(f"Output dir: {cmake_output_dir}") + print(f"Build type: {cmake_build_type}") + subprocess.check_call(cmake_build_argv, cwd=self.build_temp, env=env) + + print() + +setuptools.setup( + name = "b-asic", + version = "0.0.1", + author = "Adam Jakobsson, Angus Lothian, Arvid Westerlund, Felix Goding, Ivar Härnqvist, Jacob Wahlman, Kevin Scott, Rasmus Karlsson", + author_email = "adaja901@student.liu.se, anglo547@student.liu.se, arvwe160@student.liu.se, felgo673@student.liu.se, ivaha717@student.liu.se, jacwa448@student.liu.se, kevsc634@student.liu.se, raska119@student.liu.se", + description = "Better ASIC Toolbox", + long_description = open("README.md", "r").read(), + long_description_content_type = "text/markdown", + url = "https://gitlab.liu.se/PUM_TDDD96/B-ASIC", + classifiers = [ + "Programming Language :: Python :: 3", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + ], + python_requires = ">=3.6", + install_requires = ["pybind11>=2.3.0"], + packages = ["b_asic"], + ext_modules = [CMakeExtension("b_asic")], + cmdclass = {"build_ext": CMakeBuild}, + zip_safe = False +) \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75a77ef58b86cd29238205a078cec780a6ba9a36 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,21 @@ +#include <pybind11/pybind11.h> + +namespace py = pybind11; + +namespace asic { + +int add(int a, int b) { + return a + b; +} + +int sub(int a, int b) { + return a - b; +} + +} // namespace asic + +PYBIND11_MODULE(_b_asic, m) { + m.doc() = "Better ASIC Toolbox Extension Module."; + m.def("add", &asic::add, "A function which adds two numbers.", py::arg("a"), py::arg("b")); + m.def("sub", &asic::sub, "A function which subtracts two numbers.", py::arg("a"), py::arg("b")); +} \ No newline at end of file