Skip to content

Commit

Permalink
(WIP) Remove dependency on DynapcnnLayerHandler for deployment
Browse files Browse the repository at this point in the history
  • Loading branch information
bauerfe committed Oct 22, 2024
1 parent 482499e commit 7b63aca
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 42 deletions.
72 changes: 34 additions & 38 deletions sinabs/backend/dynapcnn/chips/dynapcnn.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import copy
from typing import List
from typing import Dict, List
from warnings import warn

import samna
Expand All @@ -10,7 +10,6 @@
from sinabs.backend.dynapcnn.config_builder import ConfigBuilder
from sinabs.backend.dynapcnn.dvs_layer import DVSLayer, expand_to_pair
from sinabs.backend.dynapcnn.dynapcnn_layer import DynapcnnLayer
from sinabs.backend.dynapcnn.dynapcnn_layer_handler import DynapcnnLayerHandler
from sinabs.backend.dynapcnn.mapping import LayerConstraints


Expand Down Expand Up @@ -77,9 +76,10 @@ def set_kill_bits(cls, layer: DynapcnnLayer, config_dict: dict) -> dict:
def get_dynapcnn_layer_config_dict(
cls,
layer: DynapcnnLayer,
layer_handler: DynapcnnLayerHandler,
all_handlers: dict,
layer2core_map: Dict[int, int],
destination_indices: List[int],
) -> dict:
# TODO: Docstring
config_dict = {}
config_dict["destinations"] = [{}, {}]

Expand Down Expand Up @@ -158,22 +158,16 @@ def get_dynapcnn_layer_config_dict(
}
)

# setting destinations config. based on destinations destination nodes of the nodes withing this `dcnnl`.
# Configure destinations
destinations = []
for node_id, destination_nodes in layer_handler.nodes_destinations.items():
for dest_node in destination_nodes:
core_id = DynapcnnLayerHandler.find_nodes_core_id(
dest_node, all_handlers
)
kernel_size = layer_handler.get_pool_kernel_size(node_id)

dest_data = {
"layer": core_id,
"enable": True,
"pooling": expand_to_pair(kernel_size if kernel_size else 1),
}

destinations.append(dest_data)
pooling_sizes = layer.pool
for dest_layer_id, pool in zip(destination_indices, pooling_sizes):
dest_data = {
"layer": layer2core_map[dest_layer_id],
"enable": True,
"pooling": expand_to_pair(pool),
}
destinations.append(dest_data)
config_dict["destinations"] = destinations

# Set kill bits
Expand All @@ -185,9 +179,9 @@ def get_dynapcnn_layer_config_dict(
def write_dynapcnn_layer_config(
cls,
layer: DynapcnnLayer,
layer2core_map: Dict[int, int],
destination_indices: List[int],
chip_layer: "CNNLayerConfig",
layer_handler: DynapcnnLayerHandler,
all_handlers: dict,
) -> None:
"""Write a single layer configuration to the dynapcnn conf object. Uses the data in `layer` to configure a `CNNLayerConfig` to be
deployed on chip.
Expand All @@ -202,22 +196,20 @@ def write_dynapcnn_layer_config(

# extracting from a DynapcnnLayer the config. variables for its CNNLayerConfig.
config_dict = cls.get_dynapcnn_layer_config_dict(
layer=layer, layer_handler=layer_handler, all_handlers=all_handlers
layer=layer,
layer2core_map=layer2core_map,
destination_indices=destination_indices,
)

# update configuration of the DYNAPCNN layer.
chip_layer.dimensions = config_dict["dimensions"]
config_dict.pop("dimensions")

# set the destinations configuration.
for i in range(len(config_dict["destinations"])):
chip_layer.destinations[i].layer = config_dict["destinations"][i]["layer"]
chip_layer.destinations[i].enable = config_dict["destinations"][i]["enable"]
chip_layer.destinations[i].pooling = config_dict["destinations"][i][
"pooling"
]

config_dict.pop("destinations")
for dest_idx, destination in enumerate(config_dict.pop("destinations")):
chip_layer.destinations[dest_idx].layer = destination["layer"]
chip_layer.destinations[dest_idx].enable = destination["enable"]
chip_layer.destinations[dest_idx].pooling = destination["pooling"]

# set remaining configuration.
for param, value in config_dict.items():
Expand All @@ -227,7 +219,13 @@ def write_dynapcnn_layer_config(
raise TypeError(f"Unexpected parameter {param} or value. {e}")

@classmethod
def build_config(cls, model: "DynapcnnNetwork") -> DynapcnnConfiguration:
def build_config(
cls,
layers: Dict[int, DynapcnnLayer],
destination_map: Dict[int, List[int]],
layer2core_map: Dict[int, int],
) -> DynapcnnConfiguration:
# TODO: Update docstring
"""Uses `DynapcnnLayer` objects to configure their equivalent chip core via a `CNNLayerConfig` object that is built
using using the `DynapcnnLayer` properties.
Expand All @@ -244,22 +242,20 @@ def build_config(cls, model: "DynapcnnNetwork") -> DynapcnnConfiguration:
has_dvs_layer = False # TODO DVSLayer not supported yet.

# Loop over layers in network and write corresponding configurations
for layer_index, ith_dcnnl in model.layers_mapper.items():
for layer_index, ith_dcnnl in layers.items():
if isinstance(ith_dcnnl, DVSLayer):
# TODO DVSLayer not supported yet.
pass

elif isinstance(ith_dcnnl, DynapcnnLayer):
# retrieve assigned core from the handler of this DynapcnnLayer (`ith_dcnnl`) instance.
chip_layer = config.cnn_layers[
model.layers_handlers[layer_index].assigned_core
]
# retrieve config dict for current layer
chip_layer = config.cnn_layers[layer2core_map[layer_index]]
# write core configuration.
cls.write_dynapcnn_layer_config(
ith_dcnnl,
chip_layer,
model.layers_handlers[layer_index],
model.layers_handlers,
destination_indices=destination_map[layer_index],
layer2core_map=layer2core_map,
)

else:
Expand Down
13 changes: 10 additions & 3 deletions sinabs/backend/dynapcnn/config_builder.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import time
from abc import ABC, abstractmethod
from typing import List
from typing import Dict, List

import samna
from samna.dynapcnn.configuration import DynapcnnConfiguration

import sinabs
import sinabs.backend
import sinabs.backend.dynapcnn

from .dvs_layer import DVSLayer
from .dynapcnn_layer import DynapcnnLayer
from .exceptions import InvalidModel
from .mapping import LayerConstraints, get_valid_mapping

Expand All @@ -35,7 +36,12 @@ def get_default_config(cls):

@classmethod
@abstractmethod
def build_config(cls, model: "DynapcnnNetwork", chip_layers: List[int]):
def build_config(
cls,
layers: Dict[int, DynapcnnLayer],
destination_map: Dict[int, List[int]],
layer2core_map: Dict[int, int],
) -> DynapcnnConfiguration:
"""Build the configuration given a model.
Parameters
Expand Down Expand Up @@ -67,6 +73,7 @@ def monitor_layers(cls, config, layers: List[int]):

@classmethod
def get_valid_mapping(cls, model: "DynapcnnNetwork") -> List[int]:
# TODO: This should accept more explicit arguments
"""Find a valid set of layers for a given model.
Parameters
Expand Down
8 changes: 7 additions & 1 deletion sinabs/backend/dynapcnn/dynapcnn_network.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,8 +395,10 @@ def _make_config(
# TODO not handling DVSLayer yet.
has_dvs_layer = isinstance(self._layers_mapper[0], DVSLayer)

# TODO: Replayce chip_layers_ordering with layer2core_map
if chip_layers_ordering == "auto":
# figure out mapping of each `DynapcnnLayer` into one core (core ID will be set in the layer's handler instance via `.assigned_core`).
# TODO: Argument should not be `self`
_ = config_builder.get_valid_mapping(self)

else:
Expand All @@ -406,7 +408,11 @@ def _make_config(
pass

# update config (config. DynapcnnLayer instances into their assigned core).
config = config_builder.build_config(self)
config = config_builder.build_config(
layers=self.dynapcnn_layers,
destination_map=self.layer_destination_map,
layer2core_map=layer2core_map,
)

# TODO not handling DVSLayer yet (this is from the old implementation, should be revised).
if self.input_shape and self.input_shape[0] == 1:
Expand Down

0 comments on commit 7b63aca

Please sign in to comment.