Collapse hwif into one file
This commit is contained in:
@@ -7,26 +7,30 @@ Any field that implements storage is defined here.
|
|||||||
Bigass struct that only contains storage elements
|
Bigass struct that only contains storage elements
|
||||||
|
|
||||||
Each field consists of:
|
Each field consists of:
|
||||||
- an always_ff block
|
- an always_comb block:
|
||||||
|
- generates the "next value" combinational signal
|
||||||
|
- May generate other intermediate strobes?
|
||||||
|
incr/decr?
|
||||||
- series of if/else statements that assign the next value in the storage element
|
- series of if/else statements that assign the next value in the storage element
|
||||||
Think of this as a flat list of "next state" conditons, ranked by their precedence as follows:
|
Think of this as a flat list of "next state" conditons, ranked by their precedence as follows:
|
||||||
- reset
|
- reset
|
||||||
|
Actually, handle this in the always_ff
|
||||||
- sw access (if sw precedence)
|
- sw access (if sw precedence)
|
||||||
- onread/onwrite
|
- onread/onwrite
|
||||||
- hw access
|
- hw access
|
||||||
- Counter
|
- Counter
|
||||||
|
beware of clear events and incr/decr events happening simultaneously
|
||||||
- next
|
- next
|
||||||
- etc
|
- etc
|
||||||
- sw access (if hw precedence)
|
- sw access (if hw precedence)
|
||||||
- onread/onwrite
|
- onread/onwrite
|
||||||
|
- always_comb block to also generate write-enable strobes for the actual
|
||||||
TODO:
|
storage element
|
||||||
What about stuff like read-clear counters that cant lose a count?
|
This is better for low-power design
|
||||||
In a traditional if/else chain, i need to be aware of the fact that its a counter
|
- an always_ff block
|
||||||
when handling the swaccess case
|
Implements the actual storage element
|
||||||
Is it possible to code this in a way where I can isolate the need to know every nuanced case here?
|
Also a tidy place to abstract the specifics of activehigh/activelow field reset
|
||||||
this may actually only apply to counters...
|
selection.
|
||||||
This is trivial in a 2-process implementation, but i'd rather avoid the overheads
|
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
Scour the RDL spec.
|
Scour the RDL spec.
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ from systemrdl.rdltypes import PropertyReference
|
|||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from .exporter import RegblockExporter
|
from .exporter import RegblockExporter
|
||||||
from .hwif.base import HwifBase
|
from .hwif import Hwif
|
||||||
from .field_logic import FieldLogic
|
from .field_logic import FieldLogic
|
||||||
from .addr_decode import AddressDecode
|
from .addr_decode import AddressDecode
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ class Dereferencer:
|
|||||||
This class provides an interface to convert conceptual SystemRDL references
|
This class provides an interface to convert conceptual SystemRDL references
|
||||||
into Verilog identifiers
|
into Verilog identifiers
|
||||||
"""
|
"""
|
||||||
def __init__(self, exporter:'RegblockExporter', top_node:Node, hwif:'HwifBase', address_decode: 'AddressDecode', field_logic: 'FieldLogic'):
|
def __init__(self, exporter:'RegblockExporter', top_node:Node, hwif:'Hwif', address_decode: 'AddressDecode', field_logic: 'FieldLogic'):
|
||||||
self.exporter = exporter
|
self.exporter = exporter
|
||||||
self.hwif = hwif
|
self.hwif = hwif
|
||||||
self.address_decode = address_decode
|
self.address_decode = address_decode
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from .readback_mux import ReadbackMux
|
|||||||
from .signals import InferredSignal
|
from .signals import InferredSignal
|
||||||
|
|
||||||
from .cpuif.apb4 import APB4_Cpuif
|
from .cpuif.apb4 import APB4_Cpuif
|
||||||
from .hwif.struct import StructHwif
|
from .hwif import Hwif
|
||||||
|
|
||||||
class RegblockExporter:
|
class RegblockExporter:
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, **kwargs):
|
||||||
@@ -50,7 +50,7 @@ class RegblockExporter:
|
|||||||
node = node.top
|
node = node.top
|
||||||
|
|
||||||
cpuif_cls = kwargs.pop("cpuif_cls", APB4_Cpuif)
|
cpuif_cls = kwargs.pop("cpuif_cls", APB4_Cpuif)
|
||||||
hwif_cls = kwargs.pop("hwif_cls", StructHwif)
|
hwif_cls = kwargs.pop("hwif_cls", Hwif)
|
||||||
module_name = kwargs.pop("module_name", node.inst_name)
|
module_name = kwargs.pop("module_name", node.inst_name)
|
||||||
package_name = kwargs.pop("package_name", module_name + "_pkg")
|
package_name = kwargs.pop("package_name", module_name + "_pkg")
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
from typing import Union, List, TYPE_CHECKING
|
from typing import TYPE_CHECKING, Union, List
|
||||||
|
from systemrdl.node import Node, SignalNode, FieldNode, AddressableNode
|
||||||
from systemrdl.node import Node, AddressableNode, FieldNode, SignalNode
|
from systemrdl.rdltypes import PropertyReference
|
||||||
|
|
||||||
from .base import HwifBase
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from ..exporter import RegblockExporter
|
from .exporter import RegblockExporter
|
||||||
|
|
||||||
class StructHwif(HwifBase):
|
class Hwif:
|
||||||
|
"""
|
||||||
|
Defines how the hardware input/output signals are generated:
|
||||||
|
- Field outputs
|
||||||
|
- Field inputs
|
||||||
|
- Signal inputs (except those that are promoted to the top)
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, exporter: 'RegblockExporter', top_node: Node, package_name: str):
|
def __init__(self, exporter: 'RegblockExporter', top_node: Node, package_name: str):
|
||||||
super().__init__(exporter, top_node, package_name)
|
self.exporter = exporter
|
||||||
|
self.top_node = top_node
|
||||||
|
self.package_name = package_name
|
||||||
|
|
||||||
self.has_input_struct = None
|
self.has_input_struct = None
|
||||||
self.has_output_struct = None
|
self.has_output_struct = None
|
||||||
@@ -18,6 +24,9 @@ class StructHwif(HwifBase):
|
|||||||
|
|
||||||
|
|
||||||
def get_package_declaration(self) -> str:
|
def get_package_declaration(self) -> str:
|
||||||
|
"""
|
||||||
|
If this hwif requires a package, generate the string
|
||||||
|
"""
|
||||||
lines = []
|
lines = []
|
||||||
|
|
||||||
lines.append(f"package {self.package_name};")
|
lines.append(f"package {self.package_name};")
|
||||||
@@ -49,6 +58,7 @@ class StructHwif(HwifBase):
|
|||||||
|
|
||||||
return ",\n".join(lines)
|
return ",\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
# Struct generation functions
|
# Struct generation functions
|
||||||
#---------------------------------------------------------------------------
|
#---------------------------------------------------------------------------
|
||||||
@@ -180,3 +190,58 @@ class StructHwif(HwifBase):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
return contents
|
return contents
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
# hwif utility functions
|
||||||
|
#---------------------------------------------------------------------------
|
||||||
|
def has_value_input(self, obj: Union[FieldNode, SignalNode]) -> bool:
|
||||||
|
"""
|
||||||
|
Returns True if the object infers an input wire in the hwif
|
||||||
|
"""
|
||||||
|
if isinstance(obj, FieldNode):
|
||||||
|
return obj.is_hw_writable
|
||||||
|
elif isinstance(obj, SignalNode):
|
||||||
|
# Signals are implicitly always inputs
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
raise RuntimeError
|
||||||
|
|
||||||
|
|
||||||
|
def has_value_output(self, obj: FieldNode) -> bool:
|
||||||
|
"""
|
||||||
|
Returns True if the object infers an output wire in the hwif
|
||||||
|
"""
|
||||||
|
# TODO: Extend this for signals and prop references?
|
||||||
|
return obj.is_hw_readable
|
||||||
|
|
||||||
|
|
||||||
|
def get_input_identifier(self, obj: Union[FieldNode, SignalNode, PropertyReference]) -> str:
|
||||||
|
"""
|
||||||
|
Returns the identifier string that best represents the input object.
|
||||||
|
|
||||||
|
if obj is:
|
||||||
|
Field: the fields input value port
|
||||||
|
Signal: signal input value
|
||||||
|
Prop reference:
|
||||||
|
could be an implied hwclr/hwset/swwe/swwel/we/wel input
|
||||||
|
Raise a runtime error if an illegal prop ref is requested, or if
|
||||||
|
the prop ref is not actually implied, but explicitly ref a component
|
||||||
|
|
||||||
|
TODO: finish this
|
||||||
|
raises an exception if obj is invalid
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
|
def get_output_identifier(self, obj: FieldNode) -> str:
|
||||||
|
"""
|
||||||
|
Returns the identifier string that best represents the output object.
|
||||||
|
|
||||||
|
if obj is:
|
||||||
|
Field: the fields output value port
|
||||||
|
Property ref: this is also part of the struct
|
||||||
|
TODO: finish this
|
||||||
|
|
||||||
|
raises an exception if obj is invalid
|
||||||
|
"""
|
||||||
|
raise NotImplementedError()
|
||||||
@@ -1 +0,0 @@
|
|||||||
from .base import HwifBase
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
from typing import TYPE_CHECKING, Union
|
|
||||||
from systemrdl.node import Node, SignalNode, FieldNode
|
|
||||||
from systemrdl.rdltypes import AccessType, PropertyReference
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from ..exporter import RegblockExporter
|
|
||||||
|
|
||||||
class HwifBase:
|
|
||||||
"""
|
|
||||||
Defines how the hardware input/output signals are generated:
|
|
||||||
- Field outputs
|
|
||||||
- Field inputs
|
|
||||||
- Signal inputs (except those that are promoted to the top)
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, exporter: 'RegblockExporter', top_node: Node, package_name: str):
|
|
||||||
self.exporter = exporter
|
|
||||||
self.top_node = top_node
|
|
||||||
self.package_name = package_name
|
|
||||||
|
|
||||||
|
|
||||||
def get_package_declaration(self) -> str:
|
|
||||||
"""
|
|
||||||
If this hwif requires a package, generate the string
|
|
||||||
"""
|
|
||||||
return ""
|
|
||||||
|
|
||||||
|
|
||||||
@property
|
|
||||||
def port_declaration(self) -> str:
|
|
||||||
"""
|
|
||||||
Returns the declaration string for all I/O ports in the hwif group
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
#---------------------------------------------------------------------------
|
|
||||||
# hwif utility functions
|
|
||||||
#---------------------------------------------------------------------------
|
|
||||||
def has_value_input(self, obj: Union[FieldNode, SignalNode]) -> bool:
|
|
||||||
"""
|
|
||||||
Returns True if the object infers an input wire in the hwif
|
|
||||||
"""
|
|
||||||
if isinstance(obj, FieldNode):
|
|
||||||
return obj.is_hw_writable
|
|
||||||
elif isinstance(obj, SignalNode):
|
|
||||||
# Signals are implicitly always inputs
|
|
||||||
return True
|
|
||||||
else:
|
|
||||||
raise RuntimeError
|
|
||||||
|
|
||||||
|
|
||||||
def has_value_output(self, obj: FieldNode) -> bool:
|
|
||||||
"""
|
|
||||||
Returns True if the object infers an output wire in the hwif
|
|
||||||
"""
|
|
||||||
# TODO: Extend this for signals and prop references?
|
|
||||||
return obj.is_hw_readable
|
|
||||||
|
|
||||||
|
|
||||||
def get_input_identifier(self, obj: Union[FieldNode, SignalNode, PropertyReference]) -> str:
|
|
||||||
"""
|
|
||||||
Returns the identifier string that best represents the input object.
|
|
||||||
|
|
||||||
if obj is:
|
|
||||||
Field: the fields input value port
|
|
||||||
Signal: signal input value
|
|
||||||
Prop reference:
|
|
||||||
could be an implied hwclr/hwset/swwe/swwel/we/wel input
|
|
||||||
Raise a runtime error if an illegal prop ref is requested, or if
|
|
||||||
the prop ref is not actually implied, but explicitly ref a component
|
|
||||||
|
|
||||||
TODO: finish this
|
|
||||||
raises an exception if obj is invalid
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
|
|
||||||
|
|
||||||
def get_output_identifier(self, obj: FieldNode) -> str:
|
|
||||||
"""
|
|
||||||
Returns the identifier string that best represents the output object.
|
|
||||||
|
|
||||||
if obj is:
|
|
||||||
Field: the fields output value port
|
|
||||||
Property ref: this is also part of the struct
|
|
||||||
TODO: finish this
|
|
||||||
|
|
||||||
raises an exception if obj is invalid
|
|
||||||
"""
|
|
||||||
raise NotImplementedError()
|
|
||||||
Reference in New Issue
Block a user