hdl._nir: implement __repr__ on NIR classes.
This commit is contained in:
parent
4014f6429c
commit
4a3a9a90e8
|
@ -71,6 +71,16 @@ class Net(int):
|
||||||
assert isinstance(value, cls)
|
assert isinstance(value, cls)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if self.is_late:
|
||||||
|
return f"(late {int(self)})"
|
||||||
|
elif self.is_const:
|
||||||
|
return f"{int(self)}"
|
||||||
|
else:
|
||||||
|
return f"{self.cell}.{self.bit}"
|
||||||
|
|
||||||
|
__str__ = __repr__
|
||||||
|
|
||||||
|
|
||||||
class Value(tuple):
|
class Value(tuple):
|
||||||
def __new__(cls, nets: 'Net | Iterable[Net]' = ()):
|
def __new__(cls, nets: 'Net | Iterable[Net]' = ()):
|
||||||
|
@ -86,6 +96,54 @@ class Value(tuple):
|
||||||
def ones(cls, digits=1):
|
def ones(cls, digits=1):
|
||||||
return cls(Net.from_const(1) for _ in range(digits))
|
return cls(Net.from_const(1) for _ in range(digits))
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
pos = 0
|
||||||
|
chunks = []
|
||||||
|
while pos < len(self):
|
||||||
|
next_pos = pos
|
||||||
|
if self[pos].is_const:
|
||||||
|
value = 0
|
||||||
|
while next_pos < len(self) and self[next_pos].is_const:
|
||||||
|
value |= self[next_pos].const << (next_pos - pos)
|
||||||
|
next_pos += 1
|
||||||
|
width = next_pos - pos
|
||||||
|
chunks.append(f"{width}'d{value}")
|
||||||
|
elif self[pos].is_late:
|
||||||
|
while (next_pos < len(self) and
|
||||||
|
self[next_pos].is_late and
|
||||||
|
self[next_pos] == self[pos] + (next_pos - pos)):
|
||||||
|
next_pos += 1
|
||||||
|
width = next_pos - pos
|
||||||
|
start = int(self[pos])
|
||||||
|
end = start + width
|
||||||
|
if width == 1:
|
||||||
|
chunks.append(f"(late {start})")
|
||||||
|
else:
|
||||||
|
chunks.append(f"(late {start}:{end})")
|
||||||
|
else:
|
||||||
|
cell = self[pos].cell
|
||||||
|
start_bit = self[pos].bit
|
||||||
|
while (next_pos < len(self) and
|
||||||
|
self[next_pos].is_cell and
|
||||||
|
self[next_pos].cell == cell and
|
||||||
|
self[next_pos].bit == start_bit + (next_pos - pos)):
|
||||||
|
next_pos += 1
|
||||||
|
width = next_pos - pos
|
||||||
|
end_bit = start_bit + width
|
||||||
|
if width == 1:
|
||||||
|
chunks.append(f"{cell}.{start_bit}")
|
||||||
|
else:
|
||||||
|
chunks.append(f"{cell}.{start_bit}:{end_bit}")
|
||||||
|
pos = next_pos
|
||||||
|
if len(chunks) == 0:
|
||||||
|
return "(0'd0)"
|
||||||
|
elif len(chunks) == 1:
|
||||||
|
return chunks[0]
|
||||||
|
else:
|
||||||
|
return f"(cat {' '.join(chunks)})"
|
||||||
|
|
||||||
|
__str__ = __repr__
|
||||||
|
|
||||||
|
|
||||||
class Netlist:
|
class Netlist:
|
||||||
"""A fine netlist. Consists of:
|
"""A fine netlist. Consists of:
|
||||||
|
@ -140,87 +198,17 @@ class Netlist:
|
||||||
for sig in self.signals:
|
for sig in self.signals:
|
||||||
self.signals[sig] = self.resolve_value(self.signals[sig])
|
self.signals[sig] = self.resolve_value(self.signals[sig])
|
||||||
|
|
||||||
def __str__(self):
|
def __repr__(self):
|
||||||
def net_to_str(net):
|
|
||||||
net = self.resolve_net(net)
|
|
||||||
if net.is_const:
|
|
||||||
return f"{net.const}"
|
|
||||||
return f"{net.cell}.{net.bit}"
|
|
||||||
def val_to_str(val):
|
|
||||||
return "{" + " ".join(net_to_str(x) for x in val) + "}"
|
|
||||||
result = []
|
result = []
|
||||||
for module_idx, module in enumerate(self.modules):
|
for module_idx, module in enumerate(self.modules):
|
||||||
result.append(f"module {module_idx} [parent {module.parent}]: {' '.join(module.name)}")
|
name = " ".join(repr(name) for name in module.name)
|
||||||
if module.submodules:
|
ports = " ".join(
|
||||||
result.append(f" submodules {' '.join(str(x) for x in module.submodules)} ")
|
f"({flow.value} {name!r} {val})"
|
||||||
result.append(f" cells {' '.join(str(x) for x in module.cells)} ")
|
for name, (val, flow) in module.ports.items()
|
||||||
for name, (val, flow) in module.ports.items():
|
)
|
||||||
result.append(f" port {name} {val_to_str(val)}: {flow}")
|
result.append(f"(module {module_idx} {module.parent} ({name}) {ports})")
|
||||||
for cell_idx, cell in enumerate(self.cells):
|
for cell_idx, cell in enumerate(self.cells):
|
||||||
result.append(f"cell {cell_idx} [module {cell.module_idx}]: ")
|
result.append(f"(cell {cell_idx} {cell.module_idx} {cell!r})")
|
||||||
if isinstance(cell, Top):
|
|
||||||
result.append("top")
|
|
||||||
for name, val in cell.ports_o.items():
|
|
||||||
result.append(f" output {name}: {val_to_str(val)}")
|
|
||||||
for name, (start, num) in cell.ports_i.items():
|
|
||||||
result.append(f" input {name}: 0.{start}..0.{start+num-1}")
|
|
||||||
for name, (start, num) in cell.ports_io.items():
|
|
||||||
result.append(f" inout {name}: 0.{start}..0.{start+num-1}")
|
|
||||||
elif isinstance(cell, Matches):
|
|
||||||
result.append(f"matches {val_to_str(cell.value)}, {' | '.join(cell.patterns)}")
|
|
||||||
elif isinstance(cell, PriorityMatch):
|
|
||||||
result.append(f"priority_match {net_to_str(cell.en)}, {val_to_str(cell.inputs)}")
|
|
||||||
elif isinstance(cell, AssignmentList):
|
|
||||||
result.append(f"list {val_to_str(cell.default)}")
|
|
||||||
for assign in cell.assignments:
|
|
||||||
result.append(f" if {net_to_str(assign.cond)} start {assign.start} <- {val_to_str(assign.value)}")
|
|
||||||
elif isinstance(cell, Operator):
|
|
||||||
inputs = ", ".join(val_to_str(input) for input in cell.inputs)
|
|
||||||
result.append(f"{cell.operator} {inputs}")
|
|
||||||
elif isinstance(cell, Part):
|
|
||||||
result.append(f"part {val_to_str(cell.value)}, {val_to_str(cell.offset)}, {cell.width}, {cell.stride}, {cell.value_signed}")
|
|
||||||
elif isinstance(cell, ArrayMux):
|
|
||||||
result.append(f"array {cell.width}, {val_to_str(cell.index)}, {', '.join(val_to_str(elem) for elem in cell.elems)}")
|
|
||||||
elif isinstance(cell, FlipFlop):
|
|
||||||
result.append(f"ff {val_to_str(cell.data)} {cell.init} @{cell.clk_edge}edge {net_to_str(cell.clk)} {net_to_str(cell.arst)}")
|
|
||||||
for attr_name, attr_value in cell.attributes.items():
|
|
||||||
result.append(f" attribute {attr_name} {attr_value}")
|
|
||||||
elif isinstance(cell, Memory):
|
|
||||||
result.append(f"memory {cell.name} {cell.width} {cell.depth} {cell.init}")
|
|
||||||
for attr_name, attr_value in cell.attributes.items():
|
|
||||||
result.append(f" attribute {attr_name} {attr_value}")
|
|
||||||
elif isinstance(cell, SyncWritePort):
|
|
||||||
result.append(f"wrport {cell.memory} {val_to_str(cell.data)} {val_to_str(cell.addr)} {val_to_str(cell.en)} @{cell.clk_edge}edge {net_to_str(cell.clk)}")
|
|
||||||
elif isinstance(cell, AsyncReadPort):
|
|
||||||
result.append(f"rdport {cell.memory} {cell.width} {val_to_str(cell.addr)}")
|
|
||||||
elif isinstance(cell, SyncReadPort):
|
|
||||||
result.append(f"rdport {cell.memory} {cell.width} {val_to_str(cell.addr)} {net_to_str(cell.en)} @{cell.clk_edge}edge {net_to_str(cell.clk)}")
|
|
||||||
for port in cell.transparent_for:
|
|
||||||
result.append(f" transparent {port}")
|
|
||||||
elif isinstance(cell, Initial):
|
|
||||||
result.append("initial")
|
|
||||||
elif isinstance(cell, AnyValue):
|
|
||||||
result.append("{cell.kind} {cell.width}")
|
|
||||||
elif isinstance(cell, AsyncProperty):
|
|
||||||
result.append(f"{cell.kind} {cell.name!r} {net_to_str(cell.test)} {net_to_str(cell.en)}")
|
|
||||||
elif isinstance(cell, SyncProperty):
|
|
||||||
result.append(f"{cell.kind} {cell.name!r} {net_to_str(cell.test)} {net_to_str(cell.en)} @{cell.clk_edge}edge {net_to_str(cell.clk)}")
|
|
||||||
elif isinstance(cell, Instance):
|
|
||||||
result.append("instance {cell.type} {cell.name}")
|
|
||||||
for attr_name, attr_value in cell.attributes.items():
|
|
||||||
result.append(f" attribute {attr_name} {attr_value}")
|
|
||||||
for attr_name, attr_value in cell.parameters.items():
|
|
||||||
result.append(f" parameter {attr_name} {attr_value}")
|
|
||||||
for attr_name, (start, num) in cell.ports_o.items():
|
|
||||||
result.append(f" output {attr_name} {cell_idx}.{start}..{cell_idx}.{start+num-1}")
|
|
||||||
for attr_name, attr_value in cell.ports_i.items():
|
|
||||||
result.append(f" input {attr_name} {val_to_str(attr_value)}")
|
|
||||||
for attr_name, attr_value in cell.ports_io.items():
|
|
||||||
result.append(f" inout {attr_name} {val_to_str(attr_value)}")
|
|
||||||
elif isinstance(cell, IOBuffer):
|
|
||||||
result.append(f"iob {val_to_str(cell.pad)} {val_to_str(cell.o)} {net_to_str(cell.oe)}")
|
|
||||||
else:
|
|
||||||
assert False # :nocov:
|
|
||||||
return "\n".join(result)
|
return "\n".join(result)
|
||||||
|
|
||||||
def add_module(self, parent, name: str):
|
def add_module(self, parent, name: str):
|
||||||
|
@ -375,6 +363,17 @@ class Top(Cell):
|
||||||
for port in self.ports_o:
|
for port in self.ports_o:
|
||||||
self.ports_o[port] = netlist.resolve_value(self.ports_o[port])
|
self.ports_o[port] = netlist.resolve_value(self.ports_o[port])
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
ports = []
|
||||||
|
for (name, val) in self.ports_o.items():
|
||||||
|
ports.append(f"(output {name!r} {val})")
|
||||||
|
for (name, (start, width)) in self.ports_i.items():
|
||||||
|
ports.append(f"(input {name!r} {start}:{start+width})")
|
||||||
|
for (name, (start, width)) in self.ports_io.items():
|
||||||
|
ports.append(f"(inout {name!r} {start}:{start+width})")
|
||||||
|
ports = " ".join(ports)
|
||||||
|
return f"(top {ports})"
|
||||||
|
|
||||||
|
|
||||||
class Operator(Cell):
|
class Operator(Cell):
|
||||||
"""Roughly corresponds to ``hdl.ast.Operator``.
|
"""Roughly corresponds to ``hdl.ast.Operator``.
|
||||||
|
@ -440,6 +439,10 @@ class Operator(Cell):
|
||||||
def resolve_nets(self, netlist: Netlist):
|
def resolve_nets(self, netlist: Netlist):
|
||||||
self.inputs = tuple(netlist.resolve_value(val) for val in self.inputs)
|
self.inputs = tuple(netlist.resolve_value(val) for val in self.inputs)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
inputs = " ".join(repr(input) for input in self.inputs)
|
||||||
|
return f"({self.operator} {inputs})"
|
||||||
|
|
||||||
|
|
||||||
class Part(Cell):
|
class Part(Cell):
|
||||||
"""Corresponds to ``hdl.ast.Part``.
|
"""Corresponds to ``hdl.ast.Part``.
|
||||||
|
@ -475,6 +478,10 @@ class Part(Cell):
|
||||||
self.value = netlist.resolve_value(self.value)
|
self.value = netlist.resolve_value(self.value)
|
||||||
self.offset = netlist.resolve_value(self.offset)
|
self.offset = netlist.resolve_value(self.offset)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
value_signed = "signed" if self.value_signed else "unsigned"
|
||||||
|
return f"(part {self.value} {value_signed} {self.offset} {self.width} {self.stride})"
|
||||||
|
|
||||||
|
|
||||||
class ArrayMux(Cell):
|
class ArrayMux(Cell):
|
||||||
"""Corresponds to ``hdl.ast.ArrayProxy``. All values in the ``elems`` array need to have
|
"""Corresponds to ``hdl.ast.ArrayProxy``. All values in the ``elems`` array need to have
|
||||||
|
@ -507,6 +514,10 @@ class ArrayMux(Cell):
|
||||||
self.elems = tuple(netlist.resolve_value(val) for val in self.elems)
|
self.elems = tuple(netlist.resolve_value(val) for val in self.elems)
|
||||||
self.index = netlist.resolve_value(self.index)
|
self.index = netlist.resolve_value(self.index)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
elems = " ".join(repr(elem) for elem in elems)
|
||||||
|
return f"(array_mux {self.width} {self.index} ({elems}))"
|
||||||
|
|
||||||
|
|
||||||
class Matches(Cell):
|
class Matches(Cell):
|
||||||
"""A combinatorial cell performing a comparison like ``Value.matches``
|
"""A combinatorial cell performing a comparison like ``Value.matches``
|
||||||
|
@ -533,6 +544,10 @@ class Matches(Cell):
|
||||||
def resolve_nets(self, netlist: Netlist):
|
def resolve_nets(self, netlist: Netlist):
|
||||||
self.value = netlist.resolve_value(self.value)
|
self.value = netlist.resolve_value(self.value)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
patterns = " ".join(self.patterns)
|
||||||
|
return f"(matches {self.value} {patterns})"
|
||||||
|
|
||||||
|
|
||||||
class PriorityMatch(Cell):
|
class PriorityMatch(Cell):
|
||||||
"""Used to represent a single switch on the control plane of processes.
|
"""Used to represent a single switch on the control plane of processes.
|
||||||
|
@ -565,6 +580,9 @@ class PriorityMatch(Cell):
|
||||||
self.en = netlist.resolve_net(self.en)
|
self.en = netlist.resolve_net(self.en)
|
||||||
self.inputs = netlist.resolve_value(self.inputs)
|
self.inputs = netlist.resolve_value(self.inputs)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"(priority_match {self.en} {self.inputs})"
|
||||||
|
|
||||||
|
|
||||||
class Assignment:
|
class Assignment:
|
||||||
"""A single assignment in an ``AssignmentList``.
|
"""A single assignment in an ``AssignmentList``.
|
||||||
|
@ -593,6 +611,10 @@ class Assignment:
|
||||||
self.cond = netlist.resolve_net(self.cond)
|
self.cond = netlist.resolve_net(self.cond)
|
||||||
self.value = netlist.resolve_value(self.value)
|
self.value = netlist.resolve_value(self.value)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
end = self.start + len(self.value)
|
||||||
|
return f"({self.cond} {self.start}:{end} {self.value})"
|
||||||
|
|
||||||
|
|
||||||
class AssignmentList(Cell):
|
class AssignmentList(Cell):
|
||||||
"""Used to represent a single assigned signal on the data plane of processes.
|
"""Used to represent a single assigned signal on the data plane of processes.
|
||||||
|
@ -633,6 +655,10 @@ class AssignmentList(Cell):
|
||||||
assign.resolve_nets(netlist)
|
assign.resolve_nets(netlist)
|
||||||
self.default = netlist.resolve_value(self.default)
|
self.default = netlist.resolve_value(self.default)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
assignments = " ".join(repr(assign) for assign in self.assignments)
|
||||||
|
return f"(assignment_list {self.default} {assignments})"
|
||||||
|
|
||||||
|
|
||||||
class FlipFlop(Cell):
|
class FlipFlop(Cell):
|
||||||
"""A flip-flop. ``data`` is the data input. ``init`` is the initial and async reset value.
|
"""A flip-flop. ``data`` is the data input. ``init`` is the initial and async reset value.
|
||||||
|
@ -673,6 +699,10 @@ class FlipFlop(Cell):
|
||||||
self.clk = netlist.resolve_net(self.clk)
|
self.clk = netlist.resolve_net(self.clk)
|
||||||
self.arst = netlist.resolve_net(self.arst)
|
self.arst = netlist.resolve_net(self.arst)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
attributes = "".join(f" (attr {key} {val!r})" for key, val in self.attributes.items())
|
||||||
|
return f"(flipflop {self.data} {self.init} {self.clk_edge} {self.clk} {self.arst}{attributes})"
|
||||||
|
|
||||||
|
|
||||||
class Memory(Cell):
|
class Memory(Cell):
|
||||||
"""Corresponds to ``Memory``. ``init`` must have length equal to ``depth``.
|
"""Corresponds to ``Memory``. ``init`` must have length equal to ``depth``.
|
||||||
|
@ -705,6 +735,11 @@ class Memory(Cell):
|
||||||
def resolve_nets(self, netlist: Netlist):
|
def resolve_nets(self, netlist: Netlist):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
init = " ".join(str(x) for x in self.init)
|
||||||
|
attributes = "".join(f" (attr {key} {val!r})" for key, val in self.attributes.items())
|
||||||
|
return f"(memory {self.name!r} {self.width} {self.depth} ({init}) {attributes})"
|
||||||
|
|
||||||
|
|
||||||
class SyncWritePort(Cell):
|
class SyncWritePort(Cell):
|
||||||
"""A single write port of a memory. This cell has no output.
|
"""A single write port of a memory. This cell has no output.
|
||||||
|
@ -742,6 +777,9 @@ class SyncWritePort(Cell):
|
||||||
self.en = netlist.resolve_value(self.en)
|
self.en = netlist.resolve_value(self.en)
|
||||||
self.clk = netlist.resolve_net(self.clk)
|
self.clk = netlist.resolve_net(self.clk)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"(write_port {self.memory} {self.data} {self.addr} {self.en} {self.clk_edge} {self.clk})"
|
||||||
|
|
||||||
|
|
||||||
class AsyncReadPort(Cell):
|
class AsyncReadPort(Cell):
|
||||||
"""A single asynchronous read port of a memory.
|
"""A single asynchronous read port of a memory.
|
||||||
|
@ -769,6 +807,10 @@ class AsyncReadPort(Cell):
|
||||||
def resolve_nets(self, netlist: Netlist):
|
def resolve_nets(self, netlist: Netlist):
|
||||||
self.addr = netlist.resolve_value(self.addr)
|
self.addr = netlist.resolve_value(self.addr)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"(read_port {self.memory} {self.width} {self.addr})"
|
||||||
|
|
||||||
|
|
||||||
class SyncReadPort(Cell):
|
class SyncReadPort(Cell):
|
||||||
"""A single synchronous read port of a memory. The cell output is the data port.
|
"""A single synchronous read port of a memory. The cell output is the data port.
|
||||||
``transparent_for`` is the set of write ports (identified by cell index) that this
|
``transparent_for`` is the set of write ports (identified by cell index) that this
|
||||||
|
@ -808,6 +850,11 @@ class SyncReadPort(Cell):
|
||||||
self.en = netlist.resolve_net(self.en)
|
self.en = netlist.resolve_net(self.en)
|
||||||
self.clk = netlist.resolve_net(self.clk)
|
self.clk = netlist.resolve_net(self.clk)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
transparent_for = " ".join(str(port) for port in self.transparent_for)
|
||||||
|
return f"(read_port {self.memory} {self.width} {self.addr} {self.en} {self.clk_edge} {self.clk} ({transparent_for}))"
|
||||||
|
|
||||||
|
|
||||||
class Initial(Cell):
|
class Initial(Cell):
|
||||||
"""Corresponds to ``Initial`` value."""
|
"""Corresponds to ``Initial`` value."""
|
||||||
|
|
||||||
|
@ -820,6 +867,9 @@ class Initial(Cell):
|
||||||
def resolve_nets(self, netlist: Netlist):
|
def resolve_nets(self, netlist: Netlist):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"(initial)"
|
||||||
|
|
||||||
|
|
||||||
class AnyValue(Cell):
|
class AnyValue(Cell):
|
||||||
"""Corresponds to ``AnyConst`` or ``AnySeq``. ``kind`` must be either ``'anyconst'``
|
"""Corresponds to ``AnyConst`` or ``AnySeq``. ``kind`` must be either ``'anyconst'``
|
||||||
|
@ -847,6 +897,9 @@ class AnyValue(Cell):
|
||||||
def resolve_nets(self, netlist: Netlist):
|
def resolve_nets(self, netlist: Netlist):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"({self.kind} {self.width})"
|
||||||
|
|
||||||
|
|
||||||
class AsyncProperty(Cell):
|
class AsyncProperty(Cell):
|
||||||
"""Corresponds to ``Assert``, ``Assume``, or ``Cover`` in the "comb" domain.
|
"""Corresponds to ``Assert``, ``Assume``, or ``Cover`` in the "comb" domain.
|
||||||
|
@ -878,6 +931,9 @@ class AsyncProperty(Cell):
|
||||||
self.test = netlist.resolve_net(self.test)
|
self.test = netlist.resolve_net(self.test)
|
||||||
self.en = netlist.resolve_net(self.en)
|
self.en = netlist.resolve_net(self.en)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"({self.kind} {self.name!r} {self.test} {self.en})"
|
||||||
|
|
||||||
|
|
||||||
class SyncProperty(Cell):
|
class SyncProperty(Cell):
|
||||||
"""Corresponds to ``Assert``, ``Assume``, or ``Cover`` in domains other than "comb".
|
"""Corresponds to ``Assert``, ``Assume``, or ``Cover`` in domains other than "comb".
|
||||||
|
@ -916,6 +972,9 @@ class SyncProperty(Cell):
|
||||||
self.en = netlist.resolve_net(self.en)
|
self.en = netlist.resolve_net(self.en)
|
||||||
self.clk = netlist.resolve_net(self.clk)
|
self.clk = netlist.resolve_net(self.clk)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"({self.kind} {self.name!r} {self.test} {self.en} {self.clk_edge} {self.clk})"
|
||||||
|
|
||||||
|
|
||||||
class Instance(Cell):
|
class Instance(Cell):
|
||||||
"""Corresponds to ``Instance``. ``type``, ``parameters`` and ``attributes`` work the same as in
|
"""Corresponds to ``Instance``. ``type``, ``parameters`` and ``attributes`` work the same as in
|
||||||
|
@ -969,6 +1028,21 @@ class Instance(Cell):
|
||||||
for port in self.ports_io:
|
for port in self.ports_io:
|
||||||
self.ports_io[port] = netlist.resolve_value(self.ports_io[port])
|
self.ports_io[port] = netlist.resolve_value(self.ports_io[port])
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
items = []
|
||||||
|
for name, val in self.parameters.items():
|
||||||
|
items.append(f"(param {name!r} {val!r})")
|
||||||
|
for name, val in self.attributes.items():
|
||||||
|
items.append(f"(attr {name!r} {val!r})")
|
||||||
|
for name, val in self.ports_i.items():
|
||||||
|
items.append(f"(input {name!r} {val})")
|
||||||
|
for name, (start, width) in self.ports_i.items():
|
||||||
|
items.append(f"(output {name!r} {start}:{start+width})")
|
||||||
|
for name, val in self.ports_io.items():
|
||||||
|
items.append(f"(inout {name!r} {val})")
|
||||||
|
items = " ".join(items)
|
||||||
|
return f"(instance {self.type!r} {self.name!r} {items})"
|
||||||
|
|
||||||
|
|
||||||
class IOBuffer(Cell):
|
class IOBuffer(Cell):
|
||||||
"""An IO buffer cell. ``pad`` must be connected to nets corresponding to an IO port
|
"""An IO buffer cell. ``pad`` must be connected to nets corresponding to an IO port
|
||||||
|
@ -1001,3 +1075,6 @@ class IOBuffer(Cell):
|
||||||
self.pad = netlist.resolve_value(self.pad)
|
self.pad = netlist.resolve_value(self.pad)
|
||||||
self.o = netlist.resolve_value(self.o)
|
self.o = netlist.resolve_value(self.o)
|
||||||
self.oe = netlist.resolve_net(self.oe)
|
self.oe = netlist.resolve_net(self.oe)
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return f"(iob {self.pad} {self.o} {self.oe})"
|
||||||
|
|
Loading…
Reference in a new issue