Skip to content
Snippets Groups Projects
Commit 38656519 authored by Oscar Gustafsson's avatar Oscar Gustafsson :bicyclist:
Browse files

Merge branch 'fetchcontent2' into 'master'

FetchContent support

See merge request !76
parents 1b75d8c3 9223bb40
No related branches found
No related tags found
1 merge request!76FetchContent support
Pipeline #59984 passed
Showing
with 314 additions and 163 deletions
Checks: "clang-analyzer-*,
cppcoreguidelines-*,
misc-*,
modernize-*,
performance-*,
portability-*,
readability-*,
-cppcoreguidelines-avoid-c-arrays,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-pro-type-union-access,
-misc-non-private-member-variables-in-classes,
-misc-no-recursion,
-modernize-avoid-c-arrays,
-modernize-use-trailing-return-type,
-readability-function-cognitive-complexity,
-readability-magic-numbers,
-readability-named-parameter"
WarningsAsErrors: "*"
HeaderFilterRegex: "src/"
cmake_minimum_required(VERSION 3.8)
project(
"B-ASIC"
project("B-ASIC"
VERSION 1.0.0
DESCRIPTION "Better ASIC Toolbox for Python 3"
LANGUAGES C CXX
)
LANGUAGES C CXX)
# Find dependencies.
find_package(fmt REQUIRED)
find_package(pybind11 CONFIG REQUIRED)
option(ASIC_USE_FETCHCONTENT "Automatically download dependencies" ON)
option(ASIC_USE_CLANG_TIDY "Use clang-tidy for static analysis" OFF)
option(ASIC_BUILDING_PYTHON_DISTRIBUTION "Don't copy compiled binaries to project directory" OFF)
set(LIBRARY_NAME "b_asic") # Name of the python library directory.
set(TARGET_NAME "_${LIBRARY_NAME}") # Name of this extension module.
# Find dependencies.
if(ASIC_USE_FETCHCONTENT)
add_subdirectory(dependencies)
else()
find_package(fmt REQUIRED)
find_package(pybind11 CONFIG REQUIRED)
endif()
# Set output directory for compiled binaries.
if(NOT CMAKE_LIBRARY_OUTPUT_DIRECTORY)
include(GNUInstallDirs)
......@@ -32,9 +37,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE "${CMAKE_LIBRARY_OUTPUT_DIRECTORY}")
# Add files to be compiled into Python module.
pybind11_add_module(
"${TARGET_NAME}"
pybind11_add_module("${TARGET_NAME}"
# Main files.
"${CMAKE_CURRENT_SOURCE_DIR}/src/main.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/src/simulation.cpp"
......@@ -53,49 +56,44 @@ pybind11_add_module(
)
# Include headers.
target_include_directories(
"${TARGET_NAME}"
PRIVATE
"${CMAKE_CURRENT_SOURCE_DIR}/src"
)
target_include_directories("${TARGET_NAME}" PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/src")
# Use C++17.
target_compile_features(
"${TARGET_NAME}"
PRIVATE
cxx_std_17
)
target_compile_features("${TARGET_NAME}" PRIVATE cxx_std_17)
# Set compiler-specific options using generator expressions.
target_compile_options(
"${TARGET_NAME}"
PRIVATE
$<$<OR:$<CXX_COMPILER_ID:GNU>,$<CXX_COMPILER_ID:Clang>>:
-W -Wall -Wextra -Werror -Wno-psabi
$<$<CONFIG:Debug>:-g>
$<$<NOT:$<CONFIG:Debug>>:-O3>
>
$<$<CXX_COMPILER_ID:MSVC>:
/W3 /WX /permissive- /utf-8
$<$<CONFIG:Debug>:/Od>
$<$<NOT:$<CONFIG:Debug>>:/Ot>
>
)
target_compile_options("${TARGET_NAME}" PRIVATE
$<$<CXX_COMPILER_ID:GNU>: -std=c++17 -Wall -Wextra -Wpedantic -Werror -Wno-psabi $<$<CONFIG:Debug>:-Og -g> $<$<CONFIG:Release>:-O3> $<$<CONFIG:MinSizeRel>:-Os> $<$<CONFIG:RelWithDebInfo>:-O3 -g>>
$<$<CXX_COMPILER_ID:Clang>: -std=c++17 -Wall -Wextra -Wpedantic -Werror $<$<CONFIG:Debug>:-Og -g> $<$<CONFIG:Release>:-O3> $<$<CONFIG:MinSizeRel>:-Os> $<$<CONFIG:RelWithDebInfo>:-O3 -g>>
$<$<CXX_COMPILER_ID:MSVC>: /std:c++17 /W3 /permissive- /WX /wd4996 /utf-8 $<$<CONFIG:Debug>:/Od> $<$<CONFIG:Release>:/Ot> $<$<CONFIG:MinSizeRel>:/Os> $<$<CONFIG:RelWithDebInfo>:/Ot /Od>>)
# Add libraries. Note: pybind11 is already added in pybind11_add_module.
target_link_libraries(
"${TARGET_NAME}"
PRIVATE
if(ASIC_USE_FETCHCONTENT)
target_link_libraries("${TARGET_NAME}" PRIVATE
dependency_fmt)
else()
target_link_libraries("${TARGET_NAME}" PRIVATE
$<TARGET_NAME_IF_EXISTS:fmt::fmt-header-only>
$<$<NOT:$<TARGET_EXISTS:fmt::fmt-header-only>>:fmt::fmt>
)
$<$<NOT:$<TARGET_EXISTS:fmt::fmt-header-only>>:fmt::fmt>)
endif()
# Set up clang-tidy.
if(ASIC_USE_CLANG_TIDY)
find_program(CLANG_TIDY NAMES clang-tidy REQUIRED)
set_property(TARGET "${TARGET_NAME}" PROPERTY CXX_CLANG_TIDY ${CLANG_TIDY})
if(MSVC)
set_target_properties("${TARGET_NAME}" PROPERTIES
VS_GLOBAL_RunCodeAnalysis true
VS_GLOBAL_EnableMicrosoftCodeAnalysis false
VS_GLOBAL_EnableClangTidyCodeAnalysis true
VS_GLOBAL_ClangTidyToolExe "${CLANG_TIDY}")
endif()
endif()
# Copy binaries to project folder for debugging during development.
if(NOT ASIC_BUILDING_PYTHON_DISTRIBUTION)
add_custom_target(
copy_binaries ALL
add_custom_target(copy_binaries ALL
COMMAND ${CMAKE_COMMAND} -E copy "$<TARGET_FILE:${TARGET_NAME}>" "${CMAKE_CURRENT_LIST_DIR}"
COMMENT "Copying binaries to ${CMAKE_CURRENT_LIST_DIR}"
DEPENDS "${TARGET_NAME}"
)
DEPENDS "${TARGET_NAME}")
endif()
......@@ -2,4 +2,4 @@ include README.md
include LICENSE
include CMakeLists.txt
include b_asic/GUI/operation_icons/*
recursive-include src *.cpp *.h
recursive-include src *.cpp *.hpp
<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.
## Development
How to build and debug the library during development.
### Prerequisites
The following packages are required in order to build the library:
* cmake 3.8+
* gcc 7+/clang 7+/msvc 16+
* fmtlib
* pybind11 2.3.0+
* python 3.6+
* Python:
* graphviz
* matplotlib
* numpy
* pybind11
* pyside2
* qtpy
* scipy
* setuptools
- cmake 3.8+
- gcc 7+/clang 7+/msvc 16+
- fmtlib
- pybind11 2.3.0+
- python 3.6+
- Python:
- graphviz
- matplotlib
- numpy
- pybind11
- pyside2
- qtpy
- scipy
- setuptools
To build a binary distribution, the following additional packages are required:
* Python:
* wheel
- Python:
- wheel
To run the test suite, the following additional packages are required:
* Python:
* pytest
* pytest-cov (for testing with coverage)
- Python:
- pytest
- pytest-cov (for testing with coverage)
To generate the documentation, the following additional packages are required:
* doxygen
- doxygen
### Using CMake directly
How to build using CMake.
#### Configuring
In `B-ASIC`:
```
mkdir build
cd build
......@@ -47,53 +57,73 @@ 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 that can be installed using pip.
#### Setup (Binary distribution)
In `B-ASIC`:
```
python3 setup.py bdist_wheel
```
The output gets written to `B-ASIC/dist/b_asic-<version>-<python_tag>-<abi_tag>-<platform_tag>.whl`.
#### Setup (Source distribution)
In `B-ASIC`:
```
python3 setup.py sdist
```
The output gets written to `B-ASIC/dist/b-asic-<version>.tar.gz`.
#### Installation (Binary distribution)
In `B-ASIC/dist`:
```
pip install b_asic-<version>-<python_tag>-<abi_tag>-<platform_tag>.whl
```
#### Installation (Source distribution)
In `B-ASIC/dist`:
```
pip install b-asic-<version>.tar.gz
```
### Running tests
How to run the tests using pytest in a virtual environment.
#### Linux/OS X
In `B-ASIC`:
```
python3 -m venv env
source env/bin/activate
......@@ -102,7 +132,9 @@ pytest
```
#### Windows
In `B-ASIC` (as admin):
```
python3 -m venv env
.\env\Scripts\activate.bat
......@@ -111,26 +143,33 @@ pytest
```
#### Test with coverage
```
pytest --cov=b_asic --cov-report html test
```
### Generating documentation
In `B-ASIC`:
```
doxygen
```
The output gets written to `B-ASIC/doc`.
## Usage
How to build and use the library as a user.
### Installation
```
pip install b_asic
```
### Importing
```
python3
>>> import b_asic as asic
......@@ -138,5 +177,6 @@ python3
```
## License
B-ASIC is distributed under the MIT license.
See the included LICENSE file for more information.
include(FetchContent)
add_subdirectory(fmt)
add_subdirectory(pybind11)
message(STATUS "Fetching fmt...")
FetchContent_Declare(fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt
GIT_TAG d141cdbeb0fb422a3fb7173b285fd38e0d1772dc # 8.0.1
)
FetchContent_MakeAvailable(fmt)
add_library(dependency_fmt INTERFACE)
target_include_directories(dependency_fmt SYSTEM INTERFACE $<TARGET_PROPERTY:fmt-header-only,INTERFACE_INCLUDE_DIRECTORIES>)
target_link_libraries(dependency_fmt INTERFACE fmt-header-only)
message(STATUS "Fetching pybind11...")
FetchContent_Declare(pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11
GIT_TAG f7b499615e14d70ab098a20deb0cdb3889998a1a # 2.8.1
)
FetchContent_MakeAvailable(pybind11)
......@@ -8,4 +8,4 @@ or to be used as a refererence for future development.
This folder contains a C++ implementation of the Simulation class designed
using Object-Oriented Programming, as opposed to the current version that uses
Data-Oriented Design. They are functionally identical, but use different
styles of programming and have different performance characteristics.
\ No newline at end of file
styles of programming and have different performance characteristics.
#ifndef ASIC_SIMULATION_CORE_OPERATIONS_H
#define ASIC_SIMULATION_CORE_OPERATIONS_H
#ifndef ASIC_SIMULATION_CORE_OPERATIONS_HPP
#define ASIC_SIMULATION_CORE_OPERATIONS_HPP
#define NOMINMAX
#include "../debug.h"
#include "../number.h"
#include "operation.h"
#include "../debug.hpp"
#include "../number.hpp"
#include "operation.hpp"
#include <algorithm>
#include <cmath>
......@@ -233,4 +232,4 @@ private:
} // namespace asic
#endif // ASIC_SIMULATION_CORE_OPERATIONS_H
\ No newline at end of file
#endif // ASIC_SIMULATION_CORE_OPERATIONS_HPP
#include "custom_operation.h"
#include "custom_operation.hpp"
#define NOMINMAX
#include <pybind11/stl.h>
namespace py = pybind11;
namespace asic {
custom_operation::custom_operation(result_key key, pybind11::object evaluate_output, pybind11::object truncate_input,
......@@ -27,4 +26,4 @@ number custom_operation::truncate_input(std::size_t index, number value, std::si
return m_truncate_input(index, value, bits).cast<number>();
}
} // namespace asic
\ No newline at end of file
} // namespace asic
#ifndef ASIC_SIMULATION_CUSTOM_OPERATION_H
#define ASIC_SIMULATION_CUSTOM_OPERATION_H
#ifndef ASIC_SIMULATION_CUSTOM_OPERATION_HPP
#define ASIC_SIMULATION_CUSTOM_OPERATION_HPP
#include "../algorithm.h"
#include "../debug.h"
#include "../number.h"
#include "operation.h"
#include "../algorithm.hpp"
#include "../debug.hpp"
#include "../number.hpp"
#include "operation.hpp"
#define NOMINMAX
#include <cstddef>
#include <fmt/format.h>
#include <functional>
......@@ -32,4 +33,4 @@ private:
} // namespace asic
#endif // ASIC_SIMULATION_CUSTOM_OPERATION_H
\ No newline at end of file
#endif // ASIC_SIMULATION_CUSTOM_OPERATION_HPP
#include "operation.h"
#include "operation.hpp"
#include "../debug.h"
#include "../debug.hpp"
#define NOMINMAX
#include <pybind11/pybind11.h>
namespace py = pybind11;
......@@ -11,7 +12,7 @@ namespace asic {
signal_source::signal_source(std::shared_ptr<const operation> op, std::size_t index, std::optional<std::size_t> bits)
: m_operation(std::move(op))
, m_index(index)
, m_bits(std::move(bits)) {}
, m_bits(bits) {}
signal_source::operator bool() const noexcept {
return static_cast<bool>(m_operation);
......@@ -100,7 +101,7 @@ signal_source const& unary_operation::input() const noexcept {
number unary_operation::evaluate_input(evaluation_context const& context) const {
auto const value = m_in.evaluate_output(context);
auto const bits = context.bits_override.value_or(m_in.bits().value_or(0));
return (context.truncate && bits) ? this->truncate_input(0, value, bits) : value;
return (context.truncate && bits != 0) ? this->truncate_input(0, value, bits) : value;
}
binary_operation::binary_operation(result_key key)
......@@ -122,13 +123,13 @@ signal_source const& binary_operation::rhs() const noexcept {
number binary_operation::evaluate_lhs(evaluation_context const& context) const {
auto const value = m_lhs.evaluate_output(context);
auto const bits = context.bits_override.value_or(m_lhs.bits().value_or(0));
return (context.truncate && bits) ? this->truncate_input(0, value, bits) : value;
return (context.truncate && bits != 0) ? this->truncate_input(0, value, bits) : value;
}
number binary_operation::evaluate_rhs(evaluation_context const& context) const {
auto const value = m_rhs.evaluate_output(context);
auto const bits = context.bits_override.value_or(m_rhs.bits().value_or(0));
return (context.truncate && bits) ? this->truncate_input(0, value, bits) : value;
return (context.truncate && bits != 0) ? this->truncate_input(0, value, bits) : value;
}
nary_operation::nary_operation(result_key key)
......@@ -148,9 +149,9 @@ std::vector<number> nary_operation::evaluate_inputs(evaluation_context const& co
for (auto const& input : m_inputs) {
auto const value = input.evaluate_output(context);
auto const bits = context.bits_override.value_or(input.bits().value_or(0));
values.push_back((context.truncate && bits) ? this->truncate_input(0, value, bits) : value);
values.push_back((context.truncate && bits != 0) ? this->truncate_input(0, value, bits) : value);
}
return values;
}
} // namespace asic
\ No newline at end of file
} // namespace asic
#ifndef ASIC_SIMULATION_OPERATION_H
#define ASIC_SIMULATION_OPERATION_H
#ifndef ASIC_SIMULATION_OPERATION_HPP
#define ASIC_SIMULATION_OPERATION_HPP
#include "../number.h"
#include "../span.h"
#include "../number.hpp"
#include "../span.hpp"
#include <cstddef>
#include <cstdint>
......@@ -26,11 +26,11 @@ using delay_map = std::unordered_map<result_key, number>;
using delay_queue = std::vector<std::pair<result_key, signal_source const*>>;
struct evaluation_context final {
result_map* results;
delay_map* delays;
delay_queue* deferred_delays;
std::optional<std::size_t> bits_override;
bool truncate;
result_map* results = nullptr;
delay_map* delays = nullptr;
delay_queue* deferred_delays = nullptr;
std::optional<std::size_t> bits_override{};
bool truncate = false;
};
class signal_source final {
......@@ -46,23 +46,25 @@ public:
[[nodiscard]] std::optional<std::size_t> bits() const noexcept;
private:
std::shared_ptr<const operation> m_operation;
std::shared_ptr<const operation> m_operation{};
std::size_t m_index = 0;
std::optional<std::size_t> m_bits;
std::optional<std::size_t> m_bits{};
};
class operation {
class operation { // NOLINT(cppcoreguidelines-special-member-functions)
public:
operation() noexcept = default;
virtual ~operation() = default;
[[nodiscard]] virtual std::size_t output_count() const noexcept = 0;
[[nodiscard]] virtual std::optional<number> current_output(std::size_t index, delay_map const& delays) const = 0;
[[nodiscard]] virtual number evaluate_output(std::size_t index, evaluation_context const& context) const = 0;
};
class abstract_operation : public operation {
class abstract_operation : public operation { // NOLINT(cppcoreguidelines-special-member-functions)
public:
explicit abstract_operation(result_key key);
virtual ~abstract_operation() = default;
~abstract_operation() override = default;
[[nodiscard]] std::optional<number> current_output(std::size_t, delay_map const&) const override;
[[nodiscard]] number evaluate_output(std::size_t index, evaluation_context const& context) const override;
......@@ -78,10 +80,10 @@ private:
result_key m_key;
};
class unary_operation : public abstract_operation {
class unary_operation : public abstract_operation { // NOLINT(cppcoreguidelines-special-member-functions)
public:
explicit unary_operation(result_key key);
virtual ~unary_operation() = default;
~unary_operation() override = default;
void connect(signal_source in);
......@@ -94,10 +96,10 @@ private:
signal_source m_in;
};
class binary_operation : public abstract_operation {
class binary_operation : public abstract_operation { // NOLINT(cppcoreguidelines-special-member-functions)
public:
explicit binary_operation(result_key key);
virtual ~binary_operation() = default;
~binary_operation() override = default;
void connect(signal_source lhs, signal_source rhs);
......@@ -112,10 +114,10 @@ private:
signal_source m_rhs;
};
class nary_operation : public abstract_operation {
class nary_operation : public abstract_operation { // NOLINT(cppcoreguidelines-special-member-functions)
public:
explicit nary_operation(result_key key);
virtual ~nary_operation() = default;
~nary_operation() override = default;
void connect(std::vector<signal_source> inputs);
......@@ -124,9 +126,9 @@ protected:
[[nodiscard]] std::vector<number> evaluate_inputs(evaluation_context const& context) const;
private:
std::vector<signal_source> m_inputs;
std::vector<signal_source> m_inputs{};
};
} // namespace asic
#endif // ASIC_SIMULATION_OPERATION_H
\ No newline at end of file
#endif // ASIC_SIMULATION_OPERATION_HPP
#include "signal_flow_graph.h"
#include "signal_flow_graph.hpp"
#include "../debug.h"
#include "../debug.hpp"
namespace py = pybind11;
......@@ -67,8 +67,8 @@ std::shared_ptr<custom_operation> signal_flow_graph_operation::add_custom_operat
std::string_view prefix, result_key key) {
auto const input_count = op.attr("input_count").cast<std::size_t>();
auto const output_count = op.attr("output_count").cast<std::size_t>();
auto const new_op = add_operation<custom_operation>(
op, added, key, op.attr("evaluate_output"), op.attr("truncate_input"), output_count);
auto new_op = add_operation<custom_operation>(
op, added, std::move(key), op.attr("evaluate_output"), op.attr("truncate_input"), output_count);
auto inputs = std::vector<signal_source>{};
inputs.reserve(input_count);
for (auto const i : range(input_count)) {
......@@ -141,4 +141,4 @@ std::shared_ptr<operation> signal_flow_graph_operation::make_operation(pybind11:
return add_custom_operation(op, added, prefix, std::move(key));
}
} // namespace asic
\ No newline at end of file
} // namespace asic
#ifndef ASIC_SIMULATION_SIGNAL_FLOW_GRAPH_H
#define ASIC_SIMULATION_SIGNAL_FLOW_GRAPH_H
#include "../algorithm.h"
#include "../debug.h"
#include "../number.h"
#include "core_operations.h"
#include "custom_operation.h"
#include "operation.h"
#include "special_operations.h"
#ifndef ASIC_SIMULATION_SIGNAL_FLOW_GRAPH_HPP
#define ASIC_SIMULATION_SIGNAL_FLOW_GRAPH_HPP
#include "../algorithm.hpp"
#include "../debug.hpp"
#include "../number.hpp"
#include "core_operations.hpp"
#include "custom_operation.hpp"
#include "operation.hpp"
#include "special_operations.hpp"
#define NOMINMAX
#include <Python.h>
#include <cstddef>
#include <fmt/format.h>
......@@ -51,7 +52,7 @@ private:
template <typename Operation, typename... Args>
[[nodiscard]] static std::shared_ptr<Operation> add_unary_operation(pybind11::handle op, added_operation_cache& added,
std::string_view prefix, Args&&... args) {
auto const new_op = add_operation<Operation>(op, added, std::forward<Args>(args)...);
auto new_op = add_operation<Operation>(op, added, std::forward<Args>(args)...);
new_op->connect(make_source(op, 0, added, prefix));
return new_op;
}
......@@ -59,7 +60,7 @@ private:
template <typename Operation, typename... Args>
[[nodiscard]] static std::shared_ptr<Operation> add_binary_operation(pybind11::handle op, added_operation_cache& added,
std::string_view prefix, Args&&... args) {
auto const new_op = add_operation<Operation>(op, added, std::forward<Args>(args)...);
auto new_op = add_operation<Operation>(op, added, std::forward<Args>(args)...);
new_op->connect(make_source(op, 0, added, prefix), make_source(op, 1, added, prefix));
return new_op;
}
......@@ -73,10 +74,10 @@ private:
[[nodiscard]] static std::shared_ptr<operation> make_operation(pybind11::handle op, added_operation_cache& added,
std::string_view prefix);
std::vector<output_operation> m_output_operations;
std::vector<std::shared_ptr<input_operation>> m_input_operations;
std::vector<output_operation> m_output_operations{};
std::vector<std::shared_ptr<input_operation>> m_input_operations{};
};
} // namespace asic
#endif // ASIC_SIMULATION_SIGNAL_FLOW_GRAPH_H
\ No newline at end of file
#endif // ASIC_SIMULATION_SIGNAL_FLOW_GRAPH_HPP
#define NOMINMAX
#include "simulation.h"
#include "simulation.hpp"
#include "../debug.h"
#include "../debug.hpp"
namespace py = pybind11;
namespace asic {
simulation::simulation(pybind11::handle sfg, std::optional<std::vector<std::optional<input_provider_t>>> input_providers)
: m_sfg("")
, m_input_functions(sfg.attr("input_count").cast<std::size_t>(), [](iteration_t) -> number { return number{}; }) {
simulation::simulation(pybind11::handle sfg, std::optional<std::vector<std::optional<input_provider_type>>> input_providers)
: m_input_functions(sfg.attr("input_count").cast<std::size_t>(), [](iteration_type) -> number { return number{}; }) {
if (input_providers) {
this->set_inputs(std::move(*input_providers));
}
......@@ -17,29 +15,30 @@ simulation::simulation(pybind11::handle sfg, std::optional<std::vector<std::opti
m_sfg.create(sfg, added);
}
void simulation::set_input(std::size_t index, input_provider_t input_provider) {
void simulation::set_input(std::size_t index, input_provider_type input_provider) {
if (index >= m_input_functions.size()) {
throw py::index_error{fmt::format("Input index out of range (expected 0-{}, got {})", m_input_functions.size() - 1, index)};
}
if (auto* const callable = std::get_if<input_function_t>(&input_provider)) {
if (auto* const callable = std::get_if<input_function_type>(&input_provider)) {
m_input_functions[index] = std::move(*callable);
} else if (auto* const numeric = std::get_if<number>(&input_provider)) {
m_input_functions[index] = [value = *numeric](iteration_t) -> number {
m_input_functions[index] = [value = *numeric](iteration_type) -> number {
return value;
};
} else if (auto* const list = std::get_if<std::vector<number>>(&input_provider)) {
if (!m_input_length) {
m_input_length = static_cast<iteration_t>(list->size());
} else if (*m_input_length != static_cast<iteration_t>(list->size())) {
m_input_length = static_cast<iteration_type>(list->size());
} else if (*m_input_length != static_cast<iteration_type>(list->size())) {
throw py::value_error{fmt::format("Inconsistent input length for simulation (was {}, got {})", *m_input_length, list->size())};
}
m_input_functions[index] = [values = std::move(*list)](iteration_t n) -> number {
m_input_functions[index] = [values = std::move(*list)](iteration_type n) -> number {
return values.at(n);
};
}
}
void simulation::set_inputs(std::vector<std::optional<input_provider_t>> input_providers) {
void simulation::set_inputs(
std::vector<std::optional<input_provider_type>> input_providers) { // NOLINT(performance-unnecessary-value-param)
if (input_providers.size() != m_input_functions.size()) {
throw py::value_error{fmt::format(
"Wrong number of inputs supplied to simulation (expected {}, got {})", m_input_functions.size(), input_providers.size())};
......@@ -55,7 +54,7 @@ std::vector<number> simulation::step(bool save_results, std::optional<std::size_
return this->run_for(1, save_results, bits_override, truncate);
}
std::vector<number> simulation::run_until(iteration_t iteration, bool save_results, std::optional<std::size_t> bits_override,
std::vector<number> simulation::run_until(iteration_type iteration, bool save_results, std::optional<std::size_t> bits_override,
bool truncate) {
auto result = std::vector<number>{};
while (m_iteration < iteration) {
......@@ -100,9 +99,9 @@ std::vector<number> simulation::run_until(iteration_t iteration, bool save_resul
return result;
}
std::vector<number> simulation::run_for(iteration_t iterations, bool save_results, std::optional<std::size_t> bits_override,
std::vector<number> simulation::run_for(iteration_type iterations, bool save_results, std::optional<std::size_t> bits_override,
bool truncate) {
if (iterations > std::numeric_limits<iteration_t>::max() - m_iteration) {
if (iterations > std::numeric_limits<iteration_type>::max() - m_iteration) {
throw py::value_error("Simulation iteration type overflow!");
}
return this->run_until(m_iteration + iterations, save_results, bits_override, truncate);
......@@ -115,7 +114,7 @@ std::vector<number> simulation::run(bool save_results, std::optional<std::size_t
throw py::index_error{"Tried to run unlimited simulation"};
}
iteration_t simulation::iteration() const noexcept {
iteration_type simulation::iteration() const noexcept {
return m_iteration;
}
......
#ifndef ASIC_SIMULATION_OOP_H
#define ASIC_SIMULATION_OOP_H
#ifndef ASIC_SIMULATION_OOP_HPP
#define ASIC_SIMULATION_OOP_HPP
#include "../number.h"
#include "core_operations.h"
#include "custom_operation.h"
#include "operation.h"
#include "signal_flow_graph.h"
#include "special_operations.h"
#include "../number.hpp"
#include "core_operations.hpp"
#include "custom_operation.hpp"
#include "operation.hpp"
#include "signal_flow_graph.hpp"
#include "special_operations.hpp"
#define NOMINMAX
#include <cstddef>
#include <cstdint>
#include <fmt/format.h>
......@@ -27,40 +28,40 @@
namespace asic {
using iteration_t = std::uint32_t;
using iteration_type = std::uint32_t;
using result_array_map = std::unordered_map<std::string, std::vector<number>>;
using input_function_t = std::function<number(iteration_t)>;
using input_provider_t = std::variant<number, std::vector<number>, input_function_t>;
using input_function_type = std::function<number(iteration_type)>;
using input_provider_type = std::variant<number, std::vector<number>, input_function_type>;
class simulation final {
public:
simulation(pybind11::handle sfg, std::optional<std::vector<std::optional<input_provider_t>>> input_providers = std::nullopt);
simulation(pybind11::handle sfg, std::optional<std::vector<std::optional<input_provider_type>>> input_providers = std::nullopt);
void set_input(std::size_t index, input_provider_t input_provider);
void set_inputs(std::vector<std::optional<input_provider_t>> input_providers);
void set_input(std::size_t index, input_provider_type input_provider);
void set_inputs(std::vector<std::optional<input_provider_type>> input_providers);
[[nodiscard]] std::vector<number> step(bool save_results, std::optional<std::size_t> bits_override, bool truncate);
[[nodiscard]] std::vector<number> run_until(iteration_t iteration, bool save_results, std::optional<std::size_t> bits_override,
[[nodiscard]] std::vector<number> run_until(iteration_type iteration, bool save_results, std::optional<std::size_t> bits_override,
bool truncate);
[[nodiscard]] std::vector<number> run_for(iteration_t iterations, bool save_results, std::optional<std::size_t> bits_override,
[[nodiscard]] std::vector<number> run_for(iteration_type iterations, bool save_results, std::optional<std::size_t> bits_override,
bool truncate);
[[nodiscard]] std::vector<number> run(bool save_results, std::optional<std::size_t> bits_override, bool truncate);
[[nodiscard]] iteration_t iteration() const noexcept;
[[nodiscard]] iteration_type iteration() const noexcept;
[[nodiscard]] pybind11::dict results() const noexcept;
void clear_results() noexcept;
void clear_state() noexcept;
private:
signal_flow_graph_operation m_sfg;
result_array_map m_results;
delay_map m_delays;
iteration_t m_iteration = 0;
std::vector<input_function_t> m_input_functions;
std::optional<iteration_t> m_input_length;
signal_flow_graph_operation m_sfg{""};
result_array_map m_results{};
delay_map m_delays{};
iteration_type m_iteration = 0;
std::optional<iteration_type> m_input_length{};
std::vector<input_function_type> m_input_functions;
};
} // namespace asic
#endif // ASIC_SIMULATION_OOP_H
\ No newline at end of file
#endif // ASIC_SIMULATION_OOP_HPP
#include "special_operations.h"
#include "special_operations.hpp"
#include "../debug.h"
#include "../debug.hpp"
namespace asic {
......
#ifndef ASIC_SIMULATION_SPECIAL_OPERATIONS_H
#define ASIC_SIMULATION_SPECIAL_OPERATIONS_H
#ifndef ASIC_SIMULATION_SPECIAL_OPERATIONS_HPP
#define ASIC_SIMULATION_SPECIAL_OPERATIONS_HPP
#include "../debug.h"
#include "../number.h"
#include "operation.h"
#include "../debug.hpp"
#include "../number.hpp"
#include "operation.hpp"
#include <cassert>
#include <cstddef>
......@@ -52,4 +52,4 @@ private:
} // namespace asic
#endif // ASIC_SIMULATION_SPECIAL_OPERATIONS_H
\ No newline at end of file
#endif // ASIC_SIMULATION_SPECIAL_OPERATIONS_HPP
......@@ -29,7 +29,7 @@ class CMakeBuild(build_ext):
os.path.dirname(self.get_ext_fullpath(ext.name)))
cmake_configure_argv = [
CMAKE_EXE, ext.sourcedir,
"-DASIC_BUILDING_PYTHON_DISTRIBUTION=true",
"-DASIC_BUILDING_PYTHON_DISTRIBUTION=ON",
"-DCMAKE_BUILD_TYPE=" + cmake_build_type,
"-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=" + cmake_output_dir,
"-DPYTHON_EXECUTABLE=" + sys.executable,
......@@ -80,7 +80,7 @@ setuptools.setup(
"pybind11>=2.3.0",
"pyside2",
"qtpy",
"graphviz",
"graphviz<=0.17",
"matplotlib",
"scipy"
],
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment