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 @@
B-ASIC architecture classes.
"""
import math
from collections import defaultdict
from collections.abc import Iterable, Iterator
from io import TextIOWrapper
......@@ -262,8 +263,11 @@ class Resource(HardwareBlock):
"""
fig, ax = plt.subplots(layout="constrained")
self.plot_content(ax, **kwargs)
height = 0.4
if title:
height = 0.8
fig.suptitle(title)
fig.set_figheight(math.floor(max(ax.get_ylim())) * 0.3 + height)
fig.show() # type: ignore
@property
......@@ -296,6 +300,7 @@ class Resource(HardwareBlock):
"""
fig, ax = plt.subplots(layout="constrained")
self.plot_content(ax)
fig.set_figheight(math.floor(max(ax.get_ylim())) * 0.3 + 0.4)
return fig
@property
......
......@@ -3,7 +3,7 @@ import re
from collections import Counter, defaultdict
from collections.abc import Iterable
from functools import reduce
from math import log2
from math import floor, log2
from typing import Literal, TypeVar
import matplotlib.pyplot as plt
......@@ -111,7 +111,7 @@ def draw_exclusion_graph_coloring(
import networkx as nx
import matplotlib.pyplot as plt
_, ax = plt.subplots()
fig, ax = plt.subplots()
collection = ProcessCollection(...)
exclusion_graph = collection.create_exclusion_graph_from_ports(
read_ports=1,
......@@ -120,7 +120,7 @@ def draw_exclusion_graph_coloring(
)
coloring = nx.greedy_color(exclusion_graph)
draw_exclusion_graph_coloring(exclusion_graph, coloring, ax=ax)
plt.show()
fig.show()
Parameters
----------
......@@ -735,8 +735,11 @@ class ProcessCollection:
show_markers=show_markers,
allow_excessive_lifetimes=allow_excessive_lifetimes,
)
height = 0.4
if title:
height = 0.8
fig.suptitle(title)
fig.set_figheight(floor(max(ax.get_ylim())) * 0.3 + height)
fig.show() # type: ignore
def create_exclusion_graph_from_ports(
......
......@@ -737,7 +737,9 @@ class Schedule:
self, operation_height: float = 1.0, operation_gap: float = OPERATION_GAP
):
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(
self, op: Operation, time: int, op_laps: dict[GraphID, int]
......@@ -1053,7 +1055,7 @@ class Schedule:
"""Get a list of all TypeNames used in the Schedule."""
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
) -> float:
y_location = self._y_locations[graph_id]
......@@ -1065,12 +1067,17 @@ class Schedule:
self._y_locations[graph_id] = y_location
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.
Inputs, outputs, dontcares, and sinks are located adjacent to the operations that
they are connected to.
See Also
--------
move_y_location
set_y_location
"""
for i, graph_id in enumerate(
sorted(self._start_times, key=self._start_times.get)
......@@ -1172,25 +1179,24 @@ class Schedule:
else:
if end[0] == start[0]:
path = Path(
[
start,
[start[0] + SPLINE_OFFSET, start[1]],
[start[0] - SPLINE_OFFSET, end[1]],
end,
],
[Path.MOVETO] + [Path.CURVE4] * 3,
)
middle_points = [
[start[0] + SPLINE_OFFSET, start[1]],
[start[0] - SPLINE_OFFSET, end[1]],
]
else:
path = Path(
[
start,
[(start[0] + end[0]) / 2, start[1]],
[(start[0] + end[0]) / 2, end[1]],
end,
],
[Path.MOVETO] + [Path.CURVE4] * 3,
)
middle_points = [
[(start[0] + end[0]) / 2, start[1]],
[(start[0] + end[0]) / 2, end[1]],
]
path = Path(
[
start,
*middle_points,
end,
],
[Path.MOVETO] + [Path.CURVE4] * 3,
)
path_patch = PathPatch(
path,
fc='none',
......@@ -1221,7 +1227,7 @@ class Schedule:
ax.set_axisbelow(True)
ax.grid()
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))
# Rewrite to make better use of NumPy
(
......@@ -1278,14 +1284,16 @@ class Schedule:
for graph_id, op_start_time in self._start_times.items():
operation = cast(Operation, self._sfg.find_by_id(graph_id))
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_signal in output_port.signals:
destination = cast(InputPort, output_signal.destination)
destination_op = destination.operation
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_in_coordinates = (
......@@ -1306,7 +1314,7 @@ class Schedule:
# Get operation with maximum position
max_pos_graph_id = max(self._y_locations, key=self._y_locations.get)
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
+ (OPERATION_GAP if operation_gap is None else operation_gap)
)
......@@ -1384,9 +1392,7 @@ class Schedule:
Generate an SVG of the schedule. This is automatically displayed in e.g.
Jupyter Qt console.
"""
height = len(self._start_times) * 0.3 + 0.7
fig, ax = plt.subplots(figsize=(12, height), layout="constrained")
self._plot_schedule(ax)
fig = self._get_figure()
buffer = io.StringIO()
fig.savefig(buffer, format="svg")
......
This diff is collapsed.
......@@ -319,7 +319,9 @@ class SchedulerItem(SchedulerEvent, QGraphicsItemGroup):
op_item = self._operation_items[graph_id]
op_item.setPos(
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:
......
......@@ -7,7 +7,7 @@ Contains the signal flow graph operation.
import itertools
import re
import warnings
from collections import defaultdict, deque
from collections import Counter, defaultdict, deque
from collections.abc import Iterable, MutableSet, Sequence
from fractions import Fraction
from io import StringIO
......@@ -2066,6 +2066,10 @@ class SFG(AbstractOperation):
paths.append(newpath)
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"]:
"""Edit SFG in GUI."""
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
......@@ -31,7 +32,8 @@ schedule1 = Schedule(sfg, scheduler=ASAPScheduler())
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}
input_times = {f"in{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
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
......@@ -44,26 +46,27 @@ print("Scheduling time:", schedule.schedule_time)
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}
schedule = Schedule(sfg, scheduler=EarliestDeadlineScheduler(resources))
print("Scheduling time:", schedule.schedule_time)
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))
print("Scheduling time:", schedule.schedule_time)
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))
print("Scheduling time:", schedule.schedule_time)
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.
input_times = {
"in0": 0,
......