Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • da/B-ASIC
  • lukja239/B-ASIC
  • robal695/B-ASIC
3 results
Show changes
Commits on Source (2)
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
B-ASIC architecture classes. B-ASIC architecture classes.
""" """
import math
from collections import defaultdict from collections import defaultdict
from collections.abc import Iterable, Iterator from collections.abc import Iterable, Iterator
from io import TextIOWrapper from io import TextIOWrapper
...@@ -262,8 +263,11 @@ class Resource(HardwareBlock): ...@@ -262,8 +263,11 @@ class Resource(HardwareBlock):
""" """
fig, ax = plt.subplots(layout="constrained") fig, ax = plt.subplots(layout="constrained")
self.plot_content(ax, **kwargs) self.plot_content(ax, **kwargs)
height = 0.4
if title: if title:
height = 0.8
fig.suptitle(title) fig.suptitle(title)
fig.set_figheight(math.floor(max(ax.get_ylim())) * 0.3 + height)
fig.show() # type: ignore fig.show() # type: ignore
@property @property
...@@ -296,6 +300,7 @@ class Resource(HardwareBlock): ...@@ -296,6 +300,7 @@ class Resource(HardwareBlock):
""" """
fig, ax = plt.subplots(layout="constrained") fig, ax = plt.subplots(layout="constrained")
self.plot_content(ax) self.plot_content(ax)
fig.set_figheight(math.floor(max(ax.get_ylim())) * 0.3 + 0.4)
return fig return fig
@property @property
......
...@@ -3,7 +3,7 @@ import re ...@@ -3,7 +3,7 @@ import re
from collections import Counter, defaultdict from collections import Counter, defaultdict
from collections.abc import Iterable from collections.abc import Iterable
from functools import reduce from functools import reduce
from math import log2 from math import floor, log2
from typing import Literal, TypeVar from typing import Literal, TypeVar
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
...@@ -111,7 +111,7 @@ def draw_exclusion_graph_coloring( ...@@ -111,7 +111,7 @@ def draw_exclusion_graph_coloring(
import networkx as nx import networkx as nx
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
_, ax = plt.subplots() fig, ax = plt.subplots()
collection = ProcessCollection(...) collection = ProcessCollection(...)
exclusion_graph = collection.create_exclusion_graph_from_ports( exclusion_graph = collection.create_exclusion_graph_from_ports(
read_ports=1, read_ports=1,
...@@ -120,7 +120,7 @@ def draw_exclusion_graph_coloring( ...@@ -120,7 +120,7 @@ def draw_exclusion_graph_coloring(
) )
coloring = nx.greedy_color(exclusion_graph) coloring = nx.greedy_color(exclusion_graph)
draw_exclusion_graph_coloring(exclusion_graph, coloring, ax=ax) draw_exclusion_graph_coloring(exclusion_graph, coloring, ax=ax)
plt.show() fig.show()
Parameters Parameters
---------- ----------
...@@ -735,8 +735,11 @@ class ProcessCollection: ...@@ -735,8 +735,11 @@ class ProcessCollection:
show_markers=show_markers, show_markers=show_markers,
allow_excessive_lifetimes=allow_excessive_lifetimes, allow_excessive_lifetimes=allow_excessive_lifetimes,
) )
height = 0.4
if title: if title:
height = 0.8
fig.suptitle(title) fig.suptitle(title)
fig.set_figheight(floor(max(ax.get_ylim())) * 0.3 + height)
fig.show() # type: ignore fig.show() # type: ignore
def create_exclusion_graph_from_ports( def create_exclusion_graph_from_ports(
......
...@@ -737,7 +737,9 @@ class Schedule: ...@@ -737,7 +737,9 @@ class Schedule:
self, operation_height: float = 1.0, operation_gap: float = OPERATION_GAP self, operation_height: float = 1.0, operation_gap: float = OPERATION_GAP
): ):
max_pos_graph_id = max(self._y_locations, key=self._y_locations.get) max_pos_graph_id = max(self._y_locations, key=self._y_locations.get)
return self._get_y_position(max_pos_graph_id, operation_height, operation_gap) return self._get_y_plot_location(
max_pos_graph_id, operation_height, operation_gap
)
def place_operation( def place_operation(
self, op: Operation, time: int, op_laps: dict[GraphID, int] self, op: Operation, time: int, op_laps: dict[GraphID, int]
...@@ -1053,7 +1055,7 @@ class Schedule: ...@@ -1053,7 +1055,7 @@ class Schedule:
"""Get a list of all TypeNames used in the Schedule.""" """Get a list of all TypeNames used in the Schedule."""
return self._sfg.get_used_type_names() return self._sfg.get_used_type_names()
def _get_y_position( def _get_y_plot_location(
self, graph_id, operation_height=1.0, operation_gap=OPERATION_GAP self, graph_id, operation_height=1.0, operation_gap=OPERATION_GAP
) -> float: ) -> float:
y_location = self._y_locations[graph_id] y_location = self._y_locations[graph_id]
...@@ -1065,12 +1067,17 @@ class Schedule: ...@@ -1065,12 +1067,17 @@ class Schedule:
self._y_locations[graph_id] = y_location self._y_locations[graph_id] = y_location
return operation_gap + y_location * (operation_height + operation_gap) return operation_gap + y_location * (operation_height + operation_gap)
def sort_y_locations_on_start_times(self): def sort_y_locations_on_start_times(self) -> None:
""" """
Sort the y-locations of the schedule based on start times of the operations. Sort the y-locations of the schedule based on start times of the operations.
Inputs, outputs, dontcares, and sinks are located adjacent to the operations that Inputs, outputs, dontcares, and sinks are located adjacent to the operations that
they are connected to. they are connected to.
See Also
--------
move_y_location
set_y_location
""" """
for i, graph_id in enumerate( for i, graph_id in enumerate(
sorted(self._start_times, key=self._start_times.get) sorted(self._start_times, key=self._start_times.get)
...@@ -1172,25 +1179,24 @@ class Schedule: ...@@ -1172,25 +1179,24 @@ class Schedule:
else: else:
if end[0] == start[0]: if end[0] == start[0]:
path = Path( middle_points = [
[ [start[0] + SPLINE_OFFSET, start[1]],
start, [start[0] - SPLINE_OFFSET, end[1]],
[start[0] + SPLINE_OFFSET, start[1]], ]
[start[0] - SPLINE_OFFSET, end[1]],
end,
],
[Path.MOVETO] + [Path.CURVE4] * 3,
)
else: else:
path = Path( middle_points = [
[ [(start[0] + end[0]) / 2, start[1]],
start, [(start[0] + end[0]) / 2, end[1]],
[(start[0] + end[0]) / 2, start[1]], ]
[(start[0] + end[0]) / 2, end[1]],
end, path = Path(
], [
[Path.MOVETO] + [Path.CURVE4] * 3, start,
) *middle_points,
end,
],
[Path.MOVETO] + [Path.CURVE4] * 3,
)
path_patch = PathPatch( path_patch = PathPatch(
path, path,
fc='none', fc='none',
...@@ -1221,7 +1227,7 @@ class Schedule: ...@@ -1221,7 +1227,7 @@ class Schedule:
ax.set_axisbelow(True) ax.set_axisbelow(True)
ax.grid() ax.grid()
for graph_id, op_start_time in self._start_times.items(): for graph_id, op_start_time in self._start_times.items():
y_pos = self._get_y_position(graph_id, operation_gap=operation_gap) y_pos = self._get_y_plot_location(graph_id, operation_gap=operation_gap)
operation = cast(Operation, self._sfg.find_by_id(graph_id)) operation = cast(Operation, self._sfg.find_by_id(graph_id))
# Rewrite to make better use of NumPy # Rewrite to make better use of NumPy
( (
...@@ -1278,14 +1284,16 @@ class Schedule: ...@@ -1278,14 +1284,16 @@ class Schedule:
for graph_id, op_start_time in self._start_times.items(): for graph_id, op_start_time in self._start_times.items():
operation = cast(Operation, self._sfg.find_by_id(graph_id)) operation = cast(Operation, self._sfg.find_by_id(graph_id))
out_coordinates = operation.get_output_coordinates() out_coordinates = operation.get_output_coordinates()
source_y_pos = self._get_y_position(graph_id, operation_gap=operation_gap) source_y_pos = self._get_y_plot_location(
graph_id, operation_gap=operation_gap
)
for output_port in operation.outputs: for output_port in operation.outputs:
for output_signal in output_port.signals: for output_signal in output_port.signals:
destination = cast(InputPort, output_signal.destination) destination = cast(InputPort, output_signal.destination)
destination_op = destination.operation destination_op = destination.operation
destination_start_time = self._start_times[destination_op.graph_id] destination_start_time = self._start_times[destination_op.graph_id]
destination_y_pos = self._get_y_position( destination_y_pos = self._get_y_plot_location(
destination_op.graph_id, operation_gap=operation_gap destination_op.graph_id, operation_gap=operation_gap
) )
destination_in_coordinates = ( destination_in_coordinates = (
...@@ -1306,7 +1314,7 @@ class Schedule: ...@@ -1306,7 +1314,7 @@ class Schedule:
# Get operation with maximum position # Get operation with maximum position
max_pos_graph_id = max(self._y_locations, key=self._y_locations.get) max_pos_graph_id = max(self._y_locations, key=self._y_locations.get)
y_position_max = ( y_position_max = (
self._get_y_position(max_pos_graph_id, operation_gap=operation_gap) self._get_y_plot_location(max_pos_graph_id, operation_gap=operation_gap)
+ 1 + 1
+ (OPERATION_GAP if operation_gap is None else operation_gap) + (OPERATION_GAP if operation_gap is None else operation_gap)
) )
...@@ -1384,9 +1392,7 @@ class Schedule: ...@@ -1384,9 +1392,7 @@ class Schedule:
Generate an SVG of the schedule. This is automatically displayed in e.g. Generate an SVG of the schedule. This is automatically displayed in e.g.
Jupyter Qt console. Jupyter Qt console.
""" """
height = len(self._start_times) * 0.3 + 0.7 fig = self._get_figure()
fig, ax = plt.subplots(figsize=(12, height), layout="constrained")
self._plot_schedule(ax)
buffer = io.StringIO() buffer = io.StringIO()
fig.savefig(buffer, format="svg") fig.savefig(buffer, format="svg")
......
This diff is collapsed.
...@@ -319,7 +319,9 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup): ...@@ -319,7 +319,9 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup):
op_item = self._operation_items[graph_id] op_item = self._operation_items[graph_id]
op_item.setPos( op_item.setPos(
self._x_axis_indent + self.schedule.start_times[graph_id], self._x_axis_indent + self.schedule.start_times[graph_id],
self.schedule._get_y_position(graph_id, OPERATION_HEIGHT, OPERATION_GAP), self.schedule._get_y_plot_location(
graph_id, OPERATION_HEIGHT, OPERATION_GAP
),
) )
def _redraw_from_start(self) -> None: def _redraw_from_start(self) -> None:
......
...@@ -7,7 +7,7 @@ Contains the signal flow graph operation. ...@@ -7,7 +7,7 @@ Contains the signal flow graph operation.
import itertools import itertools
import re import re
import warnings import warnings
from collections import defaultdict, deque from collections import Counter, defaultdict, deque
from collections.abc import Iterable, MutableSet, Sequence from collections.abc import Iterable, MutableSet, Sequence
from fractions import Fraction from fractions import Fraction
from io import StringIO from io import StringIO
...@@ -2066,6 +2066,10 @@ class SFG(AbstractOperation): ...@@ -2066,6 +2066,10 @@ class SFG(AbstractOperation):
paths.append(newpath) paths.append(newpath)
return paths return paths
def operation_counter(self) -> Counter:
"""Return a Counter with the number of instances for each type."""
return Counter(op.type_name() for op in self.operations)
def edit(self) -> dict[str, "SFG"]: def edit(self) -> dict[str, "SFG"]:
"""Edit SFG in GUI.""" """Edit SFG in GUI."""
from b_asic.GUI.main_window import start_editor from b_asic.GUI.main_window import start_editor
......
""" """
========================================= =========================================
Auto Scheduling With Custom IO times Automatic scheduling with custom IO times
========================================= =========================================
It is possible to specify the IO times and provide those to the scheduling.
""" """
from b_asic.core_operations import Butterfly, ConstantMultiplication from b_asic.core_operations import Butterfly, ConstantMultiplication
...@@ -31,7 +32,8 @@ schedule1 = Schedule(sfg, scheduler=ASAPScheduler()) ...@@ -31,7 +32,8 @@ schedule1 = Schedule(sfg, scheduler=ASAPScheduler())
schedule1.show() schedule1.show()
# %% # %%
# Generate a non-cyclic Schedule from HybridScheduler with custom IO times. # Generate a non-cyclic Schedule from HybridScheduler with custom IO times,
# one input and output per time unit
resources = {Butterfly.type_name(): 1, ConstantMultiplication.type_name(): 1} resources = {Butterfly.type_name(): 1, ConstantMultiplication.type_name(): 1}
input_times = {f"in{i}": i for i in range(points)} input_times = {f"in{i}": i for i in range(points)}
output_delta_times = {f"out{i}": i for i in range(points)} output_delta_times = {f"out{i}": i for i in range(points)}
......
""" """
================================ ==================================================
Automatic Scheduling for different latency-offsets. Automatic scheduling for different latency-offsets
================================ ==================================================
This example showcases how one can generate a schedule where the This example showcases how one can generate a schedule where the
operations have different latency offsets for the different inputs/outputs. operations have different latency offsets for the different inputs/outputs.
......
""" """
========================================= ===============================
LDLT Matrix Inversion Algorithm LDLT matrix inversion algorithm
========================================= ===============================
This provides some examples of the different list-based schedulers that are
available in B-ASIC.
""" """
from b_asic.architecture import Memory, ProcessingElement from b_asic.architecture import Memory, ProcessingElement
...@@ -44,26 +46,27 @@ print("Scheduling time:", schedule.schedule_time) ...@@ -44,26 +46,27 @@ print("Scheduling time:", schedule.schedule_time)
schedule.show() schedule.show()
# %% # %%
# Create an EarliestDeadline schedule that satisfies the resource constraints. # Create an earliest deadline schedule that uses one MADS and one Reciprocal PE.
resources = {MADS.type_name(): 1, Reciprocal.type_name(): 1} resources = {MADS.type_name(): 1, Reciprocal.type_name(): 1}
schedule = Schedule(sfg, scheduler=EarliestDeadlineScheduler(resources)) schedule = Schedule(sfg, scheduler=EarliestDeadlineScheduler(resources))
print("Scheduling time:", schedule.schedule_time) print("Scheduling time:", schedule.schedule_time)
schedule.show() schedule.show()
# %% # %%
# Create a LeastSlackTime schedule that satisfies the resource constraints. # Create a least slack-time schedule that uses one MADS and one Reciprocal PE.
schedule = Schedule(sfg, scheduler=LeastSlackTimeScheduler(resources)) schedule = Schedule(sfg, scheduler=LeastSlackTimeScheduler(resources))
print("Scheduling time:", schedule.schedule_time) print("Scheduling time:", schedule.schedule_time)
schedule.show() schedule.show()
# %% # %%
# Create a MaxFanOutScheduler schedule that satisfies the resource constraints. # Create a max fan-out schedule that uses one MADS and one Reciprocal PE.
schedule = Schedule(sfg, scheduler=MaxFanOutScheduler(resources)) schedule = Schedule(sfg, scheduler=MaxFanOutScheduler(resources))
print("Scheduling time:", schedule.schedule_time) print("Scheduling time:", schedule.schedule_time)
schedule.show() schedule.show()
# %% # %%
# Create a HybridScheduler schedule that satisfies the resource constraints with custom IO times. # Create a HybridScheduler schedule that one MADS and one Reciprocal PE with
# custom IO times.
# This is the schedule we will synthesize an architecture for. # This is the schedule we will synthesize an architecture for.
input_times = { input_times = {
"in0": 0, "in0": 0,
......