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

Add assign argument to Resource operations

parent cdcc8609
No related branches found
No related tags found
1 merge request!389Add assign argument to Resource operations
Pipeline #97487 passed
......@@ -177,16 +177,17 @@ class Resource(HardwareBlock):
return self._output_count
def _struct_def(self) -> str:
# Create GraphViz struct
inputs = [f"in{i}" for i in range(self._input_count)]
outputs = [f"out{i}" for i in range(self._output_count)]
ret = ""
if inputs:
instrs = [f"<{instr}> {instr}" for instr in inputs]
ret += f"{{{'|'.join(instrs)}}}|"
in_strs = [f"<{in_str}> {in_str}" for in_str in inputs]
ret += f"{{{'|'.join(in_strs)}}}|"
ret += f"{self.entity_name}"
if outputs:
outstrs = [f"<{outstr}> {outstr}" for outstr in outputs]
ret += f"|{{{'|'.join(outstrs)}}}"
out_strs = [f"<{out_str}> {out_str}" for out_str in outputs]
ret += f"|{{{'|'.join(out_strs)}}}"
return "{" + ret + "}"
@property
......@@ -263,7 +264,7 @@ class Resource(HardwareBlock):
def operation_type(self) -> Union[Type[MemoryProcess], Type[OperatorProcess]]:
raise NotImplementedError("ABC Resource does not implement operation_type")
def add_process(self, proc: Process):
def add_process(self, proc: Process, assign=False):
"""
Add a :class:`~b_asic.process.Process` to this :class:`Resource`.
......@@ -274,6 +275,8 @@ class Resource(HardwareBlock):
----------
proc : :class:`~b_asic.process.Process`
The process to add.
assign : bool, default=False
Whether to perform assignment of the resource after adding.
"""
if isinstance(proc, OperatorProcess):
# operation_type marks OperatorProcess associated operation.
......@@ -284,11 +287,30 @@ class Resource(HardwareBlock):
if not isinstance(proc, self.operation_type):
raise KeyError(f"{proc} not of type {self.operation_type}")
self.collection.add_process(proc)
self._assignment = None
if assign:
self.assign()
else:
self._assignment = None
def remove_process(self, proc: Process, assign: bool = False):
"""
Remove a :class:`~b_asic.process.Process` from this :class:`Resource`.
def remove_process(self, proc):
Raises :class:`KeyError` if the process being added is not of the same type
as the other processes.
Parameters
----------
proc : :class:`~b_asic.process.Process`
The process to remove.
assign : bool, default=False
Whether to perform assignment of the resource after removal.
"""
self.collection.remove_process(proc)
self._assignment = None
if assign:
self.assign()
else:
self._assignment = None
class ProcessingElement(Resource):
......@@ -674,6 +696,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
proc: Union[str, Process],
re_from: Union[str, Resource],
re_to: Union[str, Resource],
assign: bool = False,
):
"""
Move a :class:`b_asic.process.Process` from one resource to another in the
......@@ -692,8 +715,10 @@ of :class:`~b_asic.architecture.ProcessingElement`
The resource (or its given name) to move the process from.
re_to : :class:`b_asic.architecture.Resource` or string
The resource (or its given name) to move the process to.
assign : bool, default=False
Whether to perform assignment of the resources after moving.
"""
# Extract resouces from name
# Extract resources from name
if isinstance(re_from, str):
re_from = self.resource_from_name(re_from)
if isinstance(re_to, str):
......@@ -703,21 +728,24 @@ of :class:`~b_asic.architecture.ProcessingElement`
if isinstance(proc, str):
proc = re_from.collection.from_name(proc)
# Move the process.
# Move the process
if proc in re_from:
re_to.add_process(proc)
re_from.remove_process(proc)
re_to.add_process(proc, assign=assign)
re_from.remove_process(proc, assign=assign)
else:
raise KeyError(f"{proc} not in {re_from.entity_name}")
self._build_dicts()
def _digraph(self, branch_node=True) -> Digraph:
edges: DefaultDict[str, Set[Tuple[str, str]]] = defaultdict(set)
dg = Digraph(node_attr={'shape': 'record'})
# Add nodes for memories and PEs to graph
for i, mem in enumerate(self._memories):
dg.node(mem.entity_name, mem._struct_def())
for i, pe in enumerate(self._processing_elements):
dg.node(pe.entity_name, pe._struct_def())
# Create list of interconnects
edges: DefaultDict[str, Set[Tuple[str, str]]] = defaultdict(set)
for pe in self._processing_elements:
inputs, outputs = self.get_interconnects_for_pe(pe)
for i, inp in enumerate(inputs):
......@@ -729,21 +757,22 @@ of :class:`~b_asic.architecture.ProcessingElement`
)
)
for o, output in enumerate(outputs):
for (dest, port), cnt in output.items():
for (destination, port), cnt in output.items():
edges[f"{pe.entity_name}:out{o}"].add(
(
f"{dest.entity_name}:in{port}",
f"{destination.entity_name}:in{port}",
f"{cnt}",
)
)
for src_str, dest_cnts in edges.items():
if len(dest_cnts) > 1 and branch_node:
# Add edges to graph
for src_str, destination_counts in edges.items():
if len(destination_counts) > 1 and branch_node:
branch = f"{src_str}_branch".replace(":", "")
dg.node(branch, shape='point')
dg.edge(src_str, branch)
dg.edge(src_str, branch, arrowhead='none')
src_str = branch
for dest_str, cnt_str in dest_cnts:
dg.edge(src_str, dest_str, label=cnt_str)
for destination_str, cnt_str in destination_counts:
dg.edge(src_str, destination_str, label=cnt_str)
return dg
@property
......
......@@ -95,8 +95,8 @@ arch
# %%
# To reduce the amount of interconnect, the ``cuml3.0`` variable can be moved from
# ``memory0`` to ``memory2``. In this way, ``memory0``only gets variables from the
# adder and an input multiplexer can be avoided. The memoried must be assigned again as
# ``memory0`` to ``memory2``. In this way, ``memory0`` only gets variables from the
# adder and an input multiplexer can be avoided. The memories must be assigned again as
# the contents have changed.
arch.move_process('cmul3.0', 'memory0', 'memory2')
memories[0].assign()
......@@ -112,10 +112,8 @@ arch
# %%
# It is of course also possible to move ``add4.0`` to ``memory2`` to save one memory
# cell.
arch.move_process('add4.0', 'memory0', 'memory2')
memories[0].assign()
memories[2].assign()
# cell. It is possible to pass ``assign=True`` to perform assignment after moving.
arch.move_process('add4.0', 'memory0', 'memory2', assign=True)
memories[0].show_content("New assigned memory0")
memories[2].show_content("New assigned memory2")
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment