Browse Source

LogicSim clean-up and new fault injection facility. version bump.

devel
Stefan Holst 4 years ago
parent
commit
0bad95e94e
  1. 3
      setup.py
  2. 175
      src/kyupy/logic_sim.py

3
setup.py

@ -5,9 +5,10 @@ with open('README.rst', 'r') as f:
setup( setup(
name='kyupy', name='kyupy',
version='0.0.2', version='0.0.3',
description='High-performance processing and analysis of non-hierarchical VLSI designs', description='High-performance processing and analysis of non-hierarchical VLSI designs',
long_description=long_description, long_description=long_description,
long_description_content_type='text/x-rst',
packages=find_packages(where='src'), packages=find_packages(where='src'),
package_dir={'': 'src'}, package_dir={'': 'src'},
url='https://github.com/s-holst/kyupy', url='https://github.com/s-holst/kyupy',

175
src/kyupy/logic_sim.py

@ -22,40 +22,19 @@ class LogicSim:
self.zero = np.zeros((mdim, nbytes), dtype='uint8') self.zero = np.zeros((mdim, nbytes), dtype='uint8')
self.epoch = 0 self.epoch = 0
self.fork_vd1 = self.fork_vdx known_fct = [(f[:-4], getattr(self, f)) for f in dir(self) if f.endswith(f'_fct')]
self.const0_vd1 = self.const0_vdx
self.input_vd1 = self.fork_vd1
self.output_vd1 = self.fork_vd1
self.inv_vd1 = self.not_vd1
self.ibuff_vd1 = self.not_vd1
self.nbuff_vd1 = self.fork_vd1
self.xor2_vd1 = self.xor_vd1
self.fork_vd2 = self.fork_vdx
self.const0_vd2 = self.const0_vdx
self.input_vd2 = self.fork_vd2
self.output_vd2 = self.fork_vd2
self.inv_vd2 = self.not_vd2
self.ibuff_vd2 = self.not_vd2
self.nbuff_vd2 = self.fork_vd2
self.xor2_vd2 = self.xor_vd2
self.fork_vd3 = self.fork_vdx
self.const0_vd3 = self.const0_vdx
self.input_vd3 = self.fork_vd3
self.output_vd3 = self.fork_vd3
self.inv_vd3 = self.not_vd3
self.ibuff_vd3 = self.not_vd3
self.nbuff_vd3 = self.fork_vd3
self.xor2_vd3 = self.xor_vd3
known_fct = [(f[:-4], getattr(self, f)) for f in dir(self) if f.endswith(f'_vd{mdim}')]
self.node_fct = [] self.node_fct = []
for n in circuit.nodes: for n in circuit.nodes:
t = n.kind.lower().replace('__fork__', 'fork') t = n.kind.lower().replace('__fork__', 'fork')
t = t.replace('nbuff', 'fork')
t = t.replace('input', 'fork')
t = t.replace('output', 'fork')
t = t.replace('__const0__', 'const0') t = t.replace('__const0__', 'const0')
t = t.replace('__const1__', 'const1') t = t.replace('__const1__', 'const1')
t = t.replace('tieh', 'const1') t = t.replace('tieh', 'const1')
t = t.replace('ibuff', 'not')
t = t.replace('inv', 'not')
fcts = [f for n, f in known_fct if t.startswith(n)] fcts = [f for n, f in known_fct if t.startswith(n)]
if len(fcts) < 1: if len(fcts) < 1:
raise ValueError(f'Unknown node kind {n.kind}') raise ValueError(f'Unknown node kind {n.kind}')
@ -90,7 +69,7 @@ class LogicSim:
resp[...] = self.state[node.ins[0].index] resp[...] = self.state[node.ins[0].index]
# print(responses) # print(responses)
def propagate(self): 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)."""
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.index] != self.epoch: continue
@ -99,133 +78,61 @@ class LogicSim:
# print('sim', node) # print('sim', node)
self.node_fct[node.index](inputs, outputs) self.node_fct[node.index](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])
self.state_epoch[line.reader.index] = self.epoch self.state_epoch[line.reader.index] = self.epoch
self.epoch = (self.epoch + 1) % 128 self.epoch = (self.epoch + 1) % 128
def fork_vdx(self, inputs, outputs): @staticmethod
def fork_fct(inputs, outputs):
for o in outputs: o[...] = inputs[0] for o in outputs: o[...] = inputs[0]
def const0_vdx(self, _, outputs): @staticmethod
for o in outputs: o[...] = self.zero def const0_fct(_, outputs):
for o in outputs: o[...] = 0
# 2-valued simulation
def not_vd1(self, inputs, outputs):
outputs[0][0] = ~inputs[0][0]
def const1_vd1(self, _, outputs):
for o in outputs: o[...] = self.zero
self.not_vd1(outputs, outputs)
def and_vd1(self, inputs, outputs):
o = outputs[0]
o[0] = inputs[0][0]
for i in inputs[1:]: o[0] &= i[0]
def or_vd1(self, inputs, outputs):
o = outputs[0]
o[0] = inputs[0][0]
for i in inputs[1:]: o[0] |= i[0]
def xor_vd1(self, inputs, outputs):
o = outputs[0]
o[0] = inputs[0][0]
for i in inputs[1:]: o[0] ^= i[0]
def sdff_vd1(self, inputs, outputs):
outputs[0][0] = inputs[0][0]
if len(outputs) > 1:
outputs[1][0] = ~inputs[0][0]
def dff_vd1(self, inputs, outputs):
outputs[0][0] = inputs[0][0]
if len(outputs) > 1:
outputs[1][0] = ~inputs[0][0]
def nand_vd1(self, inputs, outputs):
self.and_vd1(inputs, outputs)
self.not_vd1(outputs, outputs)
def nor_vd1(self, inputs, outputs): @staticmethod
self.or_vd1(inputs, outputs) def const1_fct(_, outputs):
self.not_vd1(outputs, outputs) for o in outputs:
o[...] = 0
logic.bp_not(o, o)
def xnor_vd1(self, inputs, outputs): @staticmethod
self.xor_vd1(inputs, outputs) def not_fct(inputs, outputs):
self.not_vd1(outputs, outputs)
# 4-valued simulation
def not_vd2(self, inputs, outputs):
logic.bp_not(outputs[0], inputs[0]) logic.bp_not(outputs[0], inputs[0])
def and_vd2(self, inputs, outputs): @staticmethod
def and_fct(inputs, outputs):
logic.bp_and(outputs[0], *inputs) logic.bp_and(outputs[0], *inputs)
def or_vd2(self, inputs, outputs): @staticmethod
def or_fct(inputs, outputs):
logic.bp_or(outputs[0], *inputs) logic.bp_or(outputs[0], *inputs)
def xor_vd2(self, inputs, outputs): @staticmethod
def xor_fct(inputs, outputs):
logic.bp_xor(outputs[0], *inputs) logic.bp_xor(outputs[0], *inputs)
def sdff_vd2(self, inputs, outputs): @staticmethod
self.dff_vd2(inputs, outputs) def sdff_fct(inputs, outputs):
logic.bp_buf(outputs[0], inputs[0])
if len(outputs) > 1: if len(outputs) > 1:
logic.bp_not(outputs[1], inputs[0]) logic.bp_not(outputs[1], inputs[0])
def dff_vd2(self, inputs, outputs): @staticmethod
def dff_fct(inputs, outputs):
logic.bp_buf(outputs[0], inputs[0]) logic.bp_buf(outputs[0], inputs[0])
def nand_vd2(self, inputs, outputs): @staticmethod
self.and_vd2(inputs, outputs) def nand_fct(inputs, outputs):
self.not_vd2(outputs, outputs)
def nor_vd2(self, inputs, outputs):
self.or_vd2(inputs, outputs)
self.not_vd2(outputs, outputs)
def xnor_vd2(self, inputs, outputs):
self.xor_vd2(inputs, outputs)
self.not_vd2(outputs, outputs)
def const1_vd2(self, _, outputs):
for o in outputs: o[...] = self.zero
self.not_vd2(outputs, outputs)
# 8-valued simulation
def not_vd3(self, inputs, outputs):
logic.bp_not(outputs[0], inputs[0])
def and_vd3(self, inputs, outputs):
logic.bp_and(outputs[0], *inputs) logic.bp_and(outputs[0], *inputs)
logic.bp_not(outputs[0], outputs[0])
def or_vd3(self, inputs, outputs): @staticmethod
def nor_fct(inputs, outputs):
logic.bp_or(outputs[0], *inputs) logic.bp_or(outputs[0], *inputs)
logic.bp_not(outputs[0], outputs[0])
def xor_vd3(self, inputs, outputs): @staticmethod
def xnor_fct(inputs, outputs):
logic.bp_xor(outputs[0], *inputs) logic.bp_xor(outputs[0], *inputs)
logic.bp_not(outputs[0], outputs[0])
def sdff_vd3(self, inputs, outputs):
self.dff_vd3(inputs, outputs)
if len(outputs) > 1:
logic.bp_not(outputs[1], inputs[0])
def dff_vd3(self, inputs, outputs):
logic.bp_buf(outputs[0], inputs[0])
def nand_vd3(self, inputs, outputs):
self.and_vd3(inputs, outputs)
self.not_vd3(outputs, outputs)
def nor_vd3(self, inputs, outputs):
self.or_vd3(inputs, outputs)
self.not_vd3(outputs, outputs)
def xnor_vd3(self, inputs, outputs):
self.xor_vd3(inputs, outputs)
self.not_vd3(outputs, outputs)
def const1_vd3(self, _, outputs):
for o in outputs: o[...] = self.zero
self.not_vd3(outputs, outputs)

Loading…
Cancel
Save