Skip to content
Snippets Groups Projects
Commit dce32392 authored by Ivar Härnqvist's avatar Ivar Härnqvist
Browse files

add python system shell

parent 0e74e6a6
Branches
No related tags found
4 merge requests!67WIP: B-ASIC version 1.0.0 hotfix,!65B-ASIC version 1.0.0,!15Add changes from sprint 1 and 2 to master,!1WIP: System shell to develop branch
"""Better ASIC Toolbox""" """
Better ASIC Toolbox.
TODO: More info.
"""
from _b_asic import * from _b_asic import *
from b_asic.operation import *
def mul(a, b): from b_asic.ops import *
"""A function that multiplies two numbers""" from b_asic.pc import *
return a * b 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
"""
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
"""
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
"""
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
"""
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
"""
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
"""
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
"""
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
"""
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
...@@ -15,7 +15,7 @@ int sub(int a, int b) { ...@@ -15,7 +15,7 @@ int sub(int a, int b) {
} // namespace asic } // namespace asic
PYBIND11_MODULE(_b_asic, m) { PYBIND11_MODULE(_b_asic, m) {
m.doc() = "Better ASIC Toolbox Extension Module"; 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("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")); m.def("sub", &asic::sub, "A function which subtracts two numbers.", py::arg("a"), py::arg("b"));
} }
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment