|
|
@ -65,36 +65,32 @@ class LogicSim: |
|
|
|
|
|
|
|
|
|
|
|
:param stimuli: The input data to assign. Must be in bit-parallel storage format and in a compatible shape. |
|
|
|
:param stimuli: The input data to assign. Must be in bit-parallel storage format and in a compatible shape. |
|
|
|
:type stimuli: :py:class:`~kyupy.logic.BPArray` |
|
|
|
:type stimuli: :py:class:`~kyupy.logic.BPArray` |
|
|
|
|
|
|
|
:returns: The given stimuli object. |
|
|
|
""" |
|
|
|
""" |
|
|
|
if hasattr(stimuli, 'data'): |
|
|
|
for node, stim in zip(self.interface, stimuli.data if hasattr(stimuli, 'data') else stimuli): |
|
|
|
stimuli = stimuli.data |
|
|
|
|
|
|
|
for stim, node in zip(stimuli, self.interface): |
|
|
|
|
|
|
|
if len(node.outs) == 0: continue |
|
|
|
if len(node.outs) == 0: continue |
|
|
|
outputs = [self.state[line.index] if line else self.tmp[3] for line in node.outs] |
|
|
|
outputs = [self.state[line] if line else self.tmp[3] for line in node.outs] |
|
|
|
self.node_fct[node.index]([stim], outputs) |
|
|
|
self.node_fct[node]([stim], outputs) |
|
|
|
for line in node.outs: |
|
|
|
for line in node.outs: |
|
|
|
if line: |
|
|
|
if line is not None: self.state_epoch[line.reader] = self.epoch |
|
|
|
self.state_epoch[line.reader.index] = self.epoch |
|
|
|
|
|
|
|
for n in self.circuit.nodes: |
|
|
|
for n in self.circuit.nodes: |
|
|
|
if (n.kind == '__const1__') or (n.kind == '__const0__'): |
|
|
|
if n.kind in ('__const1__', '__const0__'): |
|
|
|
outputs = [self.state[line.index] if line else self.tmp[3] for line in n.outs] |
|
|
|
outputs = [self.state[line] if line else self.tmp[3] for line in n.outs] |
|
|
|
self.node_fct[n.index]([], outputs) |
|
|
|
self.node_fct[n]([], outputs) |
|
|
|
# print('assign const') |
|
|
|
|
|
|
|
for line in n.outs: |
|
|
|
for line in n.outs: |
|
|
|
if line: |
|
|
|
if line is not None: self.state_epoch[line.reader] = self.epoch |
|
|
|
self.state_epoch[line.reader.index] = self.epoch |
|
|
|
return stimuli |
|
|
|
|
|
|
|
|
|
|
|
def capture(self, responses): |
|
|
|
def capture(self, responses): |
|
|
|
"""Capture the current values at the primary outputs and in the state-elements (flip-flops). |
|
|
|
"""Capture the current values at the primary outputs and in the state-elements (flip-flops). |
|
|
|
|
|
|
|
|
|
|
|
:param responses: A bit-parallel storage target for the responses in a compatible shape. |
|
|
|
:param responses: A bit-parallel storage target for the responses in a compatible shape. |
|
|
|
:type responses: :py:class:`~kyupy.logic.BPArray` |
|
|
|
:type responses: :py:class:`~kyupy.logic.BPArray` |
|
|
|
|
|
|
|
:returns: The given responses object. |
|
|
|
""" |
|
|
|
""" |
|
|
|
if hasattr(responses, 'data'): |
|
|
|
for node, resp in zip(self.interface, responses.data if hasattr(responses, 'data') else responses): |
|
|
|
responses = responses.data |
|
|
|
if len(node.ins) > 0: resp[...] = self.state[node.ins[0]] |
|
|
|
for resp, node in zip(responses, self.interface): |
|
|
|
return responses |
|
|
|
if len(node.ins) == 0: continue |
|
|
|
|
|
|
|
resp[...] = self.state[node.ins[0].index] |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def propagate(self, inject_cb=None): |
|
|
|
def propagate(self, inject_cb=None): |
|
|
|
"""Propagate the input values towards the outputs (Perform all logic operations in topological order). |
|
|
|
"""Propagate the input values towards the outputs (Perform all logic operations in topological order). |
|
|
@ -117,16 +113,30 @@ class LogicSim: |
|
|
|
:type inject_cb: ``f(int, ndarray)`` |
|
|
|
:type inject_cb: ``f(int, ndarray)`` |
|
|
|
""" |
|
|
|
""" |
|
|
|
for node in self.circuit.topological_order(): |
|
|
|
for node in self.circuit.topological_order(): |
|
|
|
if self.state_epoch[node.index] != self.epoch: continue |
|
|
|
if self.state_epoch[node] != self.epoch: continue |
|
|
|
inputs = [self.state[line.index] if line else self.zero for line in node.ins] |
|
|
|
inputs = [self.state[line] if line else self.zero for line in node.ins] |
|
|
|
outputs = [self.state[line.index] if line else self.tmp[3] for line in node.outs] |
|
|
|
outputs = [self.state[line] if line else self.tmp[3] for line in node.outs] |
|
|
|
# print('sim', node) |
|
|
|
# print('sim', node) |
|
|
|
self.node_fct[node.index](inputs, outputs) |
|
|
|
self.node_fct[node](inputs, outputs) |
|
|
|
for line in node.outs: |
|
|
|
for line in node.outs: |
|
|
|
if inject_cb is not None: inject_cb(line.index, self.state[line.index]) |
|
|
|
if inject_cb is not None: inject_cb(line, self.state[line]) |
|
|
|
self.state_epoch[line.reader.index] = self.epoch |
|
|
|
self.state_epoch[line.reader] = self.epoch |
|
|
|
self.epoch = (self.epoch + 1) % 128 |
|
|
|
self.epoch = (self.epoch + 1) % 128 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def cycle(self, state, inject_cb=None): |
|
|
|
|
|
|
|
"""Assigns the given state, propagates it and captures the new state. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
:param responses: A bit-parallel array in a compatible shape holding the current circuit state. |
|
|
|
|
|
|
|
The contained data is assigned to the PI and PPI and overwritten by data at the PO and PPO after |
|
|
|
|
|
|
|
propagation. |
|
|
|
|
|
|
|
:type responses: :py:class:`~kyupy.logic.BPArray` |
|
|
|
|
|
|
|
:param inject_cb: A callback function for manipulating intermediate signal values. See :py:func:`propagate`. |
|
|
|
|
|
|
|
:returns: The given state object. |
|
|
|
|
|
|
|
""" |
|
|
|
|
|
|
|
self.assign(state) |
|
|
|
|
|
|
|
self.propagate(inject_cb) |
|
|
|
|
|
|
|
return self.capture(state) |
|
|
|
|
|
|
|
|
|
|
|
@staticmethod |
|
|
|
@staticmethod |
|
|
|
def fork_fct(inputs, outputs): |
|
|
|
def fork_fct(inputs, outputs): |
|
|
|
for o in outputs: o[...] = inputs[0] |
|
|
|
for o in outputs: o[...] = inputs[0] |
|
|
|