Skip to content
Snippets Groups Projects
Commit 5dba3f97 authored by Hugo Winbladh's avatar Hugo Winbladh Committed by Oscar Gustafsson
Browse files

Use HTML tables for architecture blocks

parent a64358e6
Branches
No related tags found
1 merge request!421Use HTML tables for architecture blocks
Pipeline #100176 passed
...@@ -170,9 +170,13 @@ class Resource(HardwareBlock): ...@@ -170,9 +170,13 @@ class Resource(HardwareBlock):
return iter(self._collection) return iter(self._collection)
def _digraph(self) -> Digraph: def _digraph(self) -> Digraph:
dg = Digraph(node_attr={'shape': 'record'}) dg = Digraph(node_attr={'shape': 'box'})
dg.node( dg.node(
self.entity_name, self._struct_def(), style='filled', fillcolor=self._color self.entity_name,
self._struct_def(),
style='filled',
fillcolor=self._color,
fontname='Times New Roman',
) )
return dg return dg
...@@ -190,15 +194,27 @@ class Resource(HardwareBlock): ...@@ -190,15 +194,27 @@ class Resource(HardwareBlock):
# Create GraphViz struct # Create GraphViz struct
inputs = [f"in{i}" for i in range(self.input_count)] inputs = [f"in{i}" for i in range(self.input_count)]
outputs = [f"out{i}" for i in range(self.output_count)] outputs = [f"out{i}" for i in range(self.output_count)]
ret = "" ret = '<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">'
table_width = max(len(inputs), len(outputs), 1)
if inputs: if inputs:
in_strs = [f"<{in_str}> {in_str}" for in_str in inputs] in_strs = [
ret += f"{{{'|'.join(in_strs)}}}|" f'<TD COLSPAN="{int(table_width/len(inputs))}"'
ret += f"<{self.entity_name}> {self.entity_name}{self._info()}" f' PORT="{in_str}">{in_str}</TD>'
for in_str in inputs
]
ret += f"<TR>{''.join(in_strs)}</TR>"
ret += (
f'<TR><TD COLSPAN="{table_width}">'
f'<B>{self.entity_name}{self._info()}</B></TD></TR>'
)
if outputs: if outputs:
out_strs = [f"<{out_str}> {out_str}" for out_str in outputs] out_strs = [
ret += f"|{{{'|'.join(out_strs)}}}" f'<TD COLSPAN="{int(table_width/len(outputs))}"'
return "{" + ret + "}" f' PORT="{out_str}">{out_str}</TD>'
for out_str in outputs
]
ret += f"<TR>{''.join(out_strs)}</TR>"
return ret + "</TABLE>>"
def _info(self): def _info(self):
return "" return ""
...@@ -825,7 +841,7 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -825,7 +841,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
colored : bool, default: True colored : bool, default: True
Whether to color the nodes. Whether to color the nodes.
""" """
dg = Digraph(node_attr={'shape': 'record'}) dg = Digraph(node_attr={'shape': 'box'})
dg.attr(splines=splines) dg.attr(splines=splines)
# Setup colors # Setup colors
pe_color = ( pe_color = (
...@@ -869,6 +885,7 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -869,6 +885,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
mem._struct_def(), mem._struct_def(),
style='filled', style='filled',
fillcolor=memory_color, fillcolor=memory_color,
fontname='Times New Roman',
) )
label = "Memory" if len(self._memories) <= 1 else "Memories" label = "Memory" if len(self._memories) <= 1 else "Memories"
c.attr(label=label, bgcolor=memory_cluster_color) c.attr(label=label, bgcolor=memory_cluster_color)
...@@ -880,6 +897,7 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -880,6 +897,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
pe._struct_def(), pe._struct_def(),
style='filled', style='filled',
fillcolor=pe_color, fillcolor=pe_color,
fontname='Times New Roman',
) )
label = ( label = (
"Processing element" "Processing element"
...@@ -896,6 +914,7 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -896,6 +914,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
pe._struct_def(), pe._struct_def(),
style='filled', style='filled',
fillcolor=io_color, fillcolor=io_color,
fontname='Times New Roman',
) )
c.attr(label="IO", bgcolor=io_cluster_color) c.attr(label="IO", bgcolor=io_cluster_color)
else: else:
...@@ -906,6 +925,7 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -906,6 +925,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
pe._struct_def(), pe._struct_def(),
style='filled', style='filled',
fillcolor=io_color, fillcolor=io_color,
fontname='Times New Roman',
) )
else: else:
for i, mem in enumerate(self._memories): for i, mem in enumerate(self._memories):
...@@ -914,6 +934,7 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -914,6 +934,7 @@ of :class:`~b_asic.architecture.ProcessingElement`
mem._struct_def(), mem._struct_def(),
style='filled', style='filled',
fillcolor=memory_color, fillcolor=memory_color,
fontname='Times New Roman',
) )
for i, pe in enumerate(self._processing_elements): for i, pe in enumerate(self._processing_elements):
dg.node( dg.node(
...@@ -954,13 +975,28 @@ of :class:`~b_asic.architecture.ProcessingElement` ...@@ -954,13 +975,28 @@ of :class:`~b_asic.architecture.ProcessingElement`
if len(source_list) > 1: if len(source_list) > 1:
# Create GraphViz struct for multiplexer # Create GraphViz struct for multiplexer
inputs = [f"in{i}" for i in range(len(source_list))] inputs = [f"in{i}" for i in range(len(source_list))]
ret = "" ret = (
in_strs = [f"<{in_str}> {in_str}" for in_str in inputs] '<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"'
ret += f"{{{'|'.join(in_strs)}}}|" ' CELLPADDING="4">'
)
in_strs = [
f'<TD COLSPAN="1" PORT="{in_str}">{in_str}</TD>'
for in_str in inputs
]
ret += f"<TR>{''.join(in_strs)}</TR>"
name = f"{destination.replace(':', '_')}_mux" name = f"{destination.replace(':', '_')}_mux"
ret += f"<{name}> {name}" ret += (
ret += "|<out0> out0" f'<TR><TD COLSPAN="{len(inputs)}"'
dg.node(name, "{" + ret + "}", style='filled', fillcolor=mux_color) f' PORT="{name}"><B>{name}</B></TD></TR>'
)
ret += f'<TR><TD COLSPAN="{len(inputs)}" PORT="out0">out0</TD></TR>'
dg.node(
name,
ret + "</TABLE>>",
style='filled',
fillcolor=mux_color,
fontname='Times New Roman',
)
# Add edge from mux output to resource input # Add edge from mux output to resource input
dg.edge(f"{name}:out0", destination) dg.edge(f"{name}:out0", destination)
......
...@@ -95,11 +95,14 @@ def test_architecture(schedule_direct_form_iir_lp_filter: Schedule): ...@@ -95,11 +95,14 @@ def test_architecture(schedule_direct_form_iir_lp_filter: Schedule):
output_pe, output_pe,
] ]
s = ( s = (
'digraph {\n\tnode [shape=record]\n\t' 'digraph {\n\tnode [shape=box]\n\t'
+ "adder" + 'adder'
+ ' [label="{{<in0> in0|<in1> in1}|' + ' [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0" CELLPADDING="4">'
+ '<adder> adder' + '<TR><TD COLSPAN="1" PORT="in0">in0</TD>'
+ '|{<out0> out0}}" fillcolor="#00B9E7" style=filled]\n}' + '<TD COLSPAN="1" PORT="in1">in1</TD></TR>'
+ '<TR><TD COLSPAN="2"><B>adder</B></TD></TR>'
+ '<TR><TD COLSPAN="2" PORT="out0">out0</TD></TR>'
+ '</TABLE>> fillcolor="#00B9E7" fontname="Times New Roman" style=filled]\n}'
) )
assert adder._digraph().source in (s, s + '\n') assert adder._digraph().source in (s, s + '\n')
...@@ -115,8 +118,14 @@ def test_architecture(schedule_direct_form_iir_lp_filter: Schedule): ...@@ -115,8 +118,14 @@ def test_architecture(schedule_direct_form_iir_lp_filter: Schedule):
for i, memory in enumerate(memories): for i, memory in enumerate(memories):
memory.set_entity_name(f"MEM{i}") memory.set_entity_name(f"MEM{i}")
s = ( s = (
'digraph {\n\tnode [shape=record]\n\tMEM0 [label="{{<in0> in0}|<MEM0>' 'digraph {\n\tnode [shape=box]\n\tMEM0'
' MEM0|{<out0> out0}}" fillcolor="#00CFB5" style=filled]\n}' + ' [label=<<TABLE BORDER="0" CELLBORDER="1"'
+ ' CELLSPACING="0" CELLPADDING="4">'
+ '<TR><TD COLSPAN="1" PORT="in0">in0</TD></TR>'
+ '<TR><TD COLSPAN="1"><B>MEM0</B></TD></TR>'
+ '<TR><TD COLSPAN="1" PORT="out0">out0</TD></TR>'
+ '</TABLE>> fillcolor="#00CFB5" fontname="Times New Roman" '
+ 'style=filled]\n}'
) )
assert memory._digraph().source in (s, s + '\n') assert memory._digraph().source in (s, s + '\n')
assert memory.schedule_time == 18 assert memory.schedule_time == 18
...@@ -149,11 +158,11 @@ def test_architecture(schedule_direct_form_iir_lp_filter: Schedule): ...@@ -149,11 +158,11 @@ def test_architecture(schedule_direct_form_iir_lp_filter: Schedule):
# Graph representation # Graph representation
# Parts are non-deterministic, but this first part seems OK # Parts are non-deterministic, but this first part seems OK
s = ( s = (
'digraph {\n\tnode [shape=record]\n\tsplines=spline\n\tsubgraph' 'digraph {\n\tnode [shape=box]\n\tsplines=spline\n\tsubgraph'
' cluster_memories' ' cluster_memories'
) )
assert architecture._digraph().source.startswith(s) assert architecture._digraph().source.startswith(s)
s = 'digraph {\n\tnode [shape=record]\n\tsplines=spline\n\tMEM0' s = 'digraph {\n\tnode [shape=box]\n\tsplines=spline\n\tMEM0'
assert architecture._digraph(cluster=False).source.startswith(s) assert architecture._digraph(cluster=False).source.startswith(s)
assert architecture.schedule_time == 18 assert architecture.schedule_time == 18
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment