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
No related branches found
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 *
def mul(a, b):
"""A function that multiplies two numbers"""
return a * b
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
"""
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) {
} // 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"));
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
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