Skip to content
Snippets Groups Projects

Add support for other types

Merged Oscar Gustafsson requested to merge archtypes into master
3 files
+ 72
72
Compare changes
  • Side-by-side
  • Inline
Files
3
+ 67
71
@@ -2,7 +2,7 @@
@@ -2,7 +2,7 @@
B-ASIC architecture classes.
B-ASIC architecture classes.
"""
"""
from collections import defaultdict
from collections import defaultdict
from typing import Dict, Iterator, List, Optional, Set, Tuple, cast
from typing import Dict, Iterable, Iterator, List, Optional, Set, Tuple, Union, cast
from graphviz import Digraph
from graphviz import Digraph
@@ -16,49 +16,39 @@ def _interconnect_dict() -> int:
@@ -16,49 +16,39 @@ def _interconnect_dict() -> int:
return 0
return 0
class Resource:
class HardwareBlock:
"""
"""
Base class for resource.
Base class for architectures and resources.
Parameters
Parameters
----------
----------
process_collection : ProcessCollection
The process collection containing processes to be mapped to resource.
entity_name : str, optional
entity_name : str, optional
The name of the resulting entity.
The name of the resulting entity.
"""
"""
def __init__(
def __init__(self, entity_name: Optional[str] = None):
self, process_collection: ProcessCollection, entity_name: Optional[str] = None
self._entity_name = None
):
if entity_name is not None:
if not len(process_collection):
self.set_entity_name(entity_name)
raise ValueError("Do not create Resource with empty ProcessCollection")
self._collection = process_collection
self._entity_name = entity_name
self._input_count = -1
self._output_count = -1
def __repr__(self):
return self.entity_name
def __iter__(self):
return iter(self._collection)
def set_entity_name(self, entity_name: str):
def set_entity_name(self, entity_name: str):
"""
"""
Set entity name of resource.
Set entity name of hardware block.
Parameters
Parameters
----------
----------
entity_name : str
entity_name : str
The entity name.
The entity name.
"""
"""
 
# Should be a better check.
 
# See https://stackoverflow.com/questions/7959587/regex-for-vhdl-identifier
 
if " " in entity_name:
 
raise ValueError("Cannot have space in entity name")
self._entity_name = entity_name
self._entity_name = entity_name
def write_code(self, path: str) -> None:
def write_code(self, path: str) -> None:
"""
"""
Write VHDL code for resource.
Write VHDL code for hardware block.
Parameters
Parameters
----------
----------
@@ -78,6 +68,45 @@ class Resource:
@@ -78,6 +68,45 @@ class Resource:
def _repr_png_(self):
def _repr_png_(self):
return self._digraph()._repr_mimebundle_(include=["image/png"])["image/png"]
return self._digraph()._repr_mimebundle_(include=["image/png"])["image/png"]
 
@property
 
def entity_name(self) -> str:
 
if self._entity_name is None:
 
return "Undefined entity name"
 
return self._entity_name
 
 
def _digraph(self) -> Digraph:
 
raise NotImplementedError()
 
 
 
class Resource(HardwareBlock):
 
"""
 
Base class for resource.
 
 
Parameters
 
----------
 
process_collection : ProcessCollection
 
The process collection containing processes to be mapped to resource.
 
entity_name : str, optional
 
The name of the resulting entity.
 
 
"""
 
 
def __init__(
 
self, process_collection: ProcessCollection, entity_name: Optional[str] = None
 
):
 
if not len(process_collection):
 
raise ValueError("Do not create Resource with empty ProcessCollection")
 
super().__init__(entity_name=entity_name)
 
self._collection = process_collection
 
self._input_count = -1
 
self._output_count = -1
 
 
def __repr__(self):
 
return self.entity_name
 
 
def __iter__(self):
 
return iter(self._collection)
 
def _digraph(self) -> Digraph:
def _digraph(self) -> Digraph:
dg = Digraph(node_attr={'shape': 'record'})
dg = Digraph(node_attr={'shape': 'record'})
dg.node(self.entity_name, self._struct_def())
dg.node(self.entity_name, self._struct_def())
@@ -106,12 +135,6 @@ class Resource:
@@ -106,12 +135,6 @@ class Resource:
ret += f"|{{{'|'.join(outstrs)}}}"
ret += f"|{{{'|'.join(outstrs)}}}"
return "{" + ret + "}"
return "{" + ret + "}"
@property
def entity_name(self) -> str:
if self._entity_name is None:
return "Undefined entity name"
return self._entity_name
class ProcessingElement(Resource):
class ProcessingElement(Resource):
"""
"""
@@ -216,32 +239,36 @@ class Memory(Resource):
@@ -216,32 +239,36 @@ class Memory(Resource):
return cast(Iterator[MemoryVariable], iter(self._collection))
return cast(Iterator[MemoryVariable], iter(self._collection))
class Architecture:
class Architecture(HardwareBlock):
"""
"""
Class representing an architecture.
Class representing an architecture.
Parameters
Parameters
----------
----------
processing_elements : set of :class:`~b_asic.architecture.ProcessingElement`
processing_elements : :class:`~b_asic.architecture.ProcessingElement` or iterable of :class:`~b_asic.architecture.ProcessingElement`
The processing elements in the architecture.
The processing elements in the architecture.
memories : set of :class:`~b_asic.architecture.Memory`
memories : `~b_asic.architecture.Memory` or iterable of :class:`~b_asic.architecture.Memory`
The memories in the architecture.
The memories in the architecture.
entity_name : str, default: "arch"
entity_name : str, default: "arch"
Name for the top-level entity.
Name for the top-level entity.
direct_interconnects : ProcessCollection, optional
direct_interconnects : :class:`~b_asic.resources.ProcessCollection`, optional
Process collection of zero-time memory variables used for direct interconnects.
Process collection of zero-time memory variables used for direct interconnects.
"""
"""
def __init__(
def __init__(
self,
self,
processing_elements: Set[ProcessingElement],
processing_elements: Union[ProcessingElement, Iterable[ProcessingElement]],
memories: Set[Memory],
memories: Union[Memory, Iterable[Memory]],
entity_name: str = "arch",
entity_name: str = "arch",
direct_interconnects: Optional[ProcessCollection] = None,
direct_interconnects: Optional[ProcessCollection] = None,
):
):
self._processing_elements = processing_elements
super().__init__(entity_name)
self._memories = memories
self._processing_elements = (
self._entity_name = entity_name
set(processing_elements)
 
if isinstance(processing_elements, ProcessingElement)
 
else processing_elements
 
)
 
self._memories = set(memories) if isinstance(memories, Memory) else memories
self._direct_interconnects = direct_interconnects
self._direct_interconnects = direct_interconnects
self._variable_inport_to_resource: Dict[InputPort, Tuple[Resource, int]] = {}
self._variable_inport_to_resource: Dict[InputPort, Tuple[Resource, int]] = {}
self._variable_outport_to_resource: Dict[OutputPort, Tuple[Resource, int]] = {}
self._variable_outport_to_resource: Dict[OutputPort, Tuple[Resource, int]] = {}
@@ -315,17 +342,6 @@ class Architecture:
@@ -315,17 +342,6 @@ class Architecture:
)
)
# Make sure all inputs and outputs in the architecture are in use
# Make sure all inputs and outputs in the architecture are in use
def write_code(self, path: str) -> None:
"""
Write HDL of architecture.
Parameters
----------
path : str
Directory to write code in.
"""
raise NotImplementedError
def get_interconnects_for_memory(self, mem: Memory):
def get_interconnects_for_memory(self, mem: Memory):
"""
"""
Return a dictionary with interconnect information for a Memory.
Return a dictionary with interconnect information for a Memory.
@@ -385,26 +401,6 @@ class Architecture:
@@ -385,26 +401,6 @@ class Architecture:
d_out[i][self._variable_outport_to_resource[output]] += 1
d_out[i][self._variable_outport_to_resource[output]] += 1
return [dict(d) for d in d_in], [dict(d) for d in d_out]
return [dict(d) for d in d_in], [dict(d) for d in d_out]
def set_entity_name(self, entity_name: str):
"""
Set entity name of architecture.
Parameters
----------
entity_name : str
The entity name.
"""
self._entity_name = entity_name
def _repr_mimebundle_(self, include=None, exclude=None):
return self._digraph()._repr_mimebundle_(include=include, exclude=exclude)
def _repr_jpeg_(self):
return self._digraph()._repr_mimebundle_(include=["image/jpeg"])["image/jpeg"]
def _repr_png_(self):
return self._digraph()._repr_mimebundle_(include=["image/png"])["image/png"]
def _digraph(self) -> Digraph:
def _digraph(self) -> Digraph:
edges = set()
edges = set()
dg = Digraph(node_attr={'shape': 'record'})
dg = Digraph(node_attr={'shape': 'record'})
@@ -438,11 +434,11 @@ class Architecture:
@@ -438,11 +434,11 @@ class Architecture:
return dg
return dg
@property
@property
def memories(self) -> Set[Memory]:
def memories(self) -> Iterable[Memory]:
return self._memories
return self._memories
@property
@property
def processing_elements(self) -> Set[ProcessingElement]:
def processing_elements(self) -> Iterable[ProcessingElement]:
return self._processing_elements
return self._processing_elements
@property
@property
Loading