diff --git a/setup.py b/setup.py index 9a0bb1b..efb49ec 100644 --- a/setup.py +++ b/setup.py @@ -5,9 +5,10 @@ with open('README.rst', 'r') as f: setup( name='kyupy', - version='0.0.2', + version='0.0.3', description='High-performance processing and analysis of non-hierarchical VLSI designs', long_description=long_description, + long_description_content_type='text/x-rst', packages=find_packages(where='src'), package_dir={'': 'src'}, url='https://github.com/s-holst/kyupy', diff --git a/src/kyupy/logic_sim.py b/src/kyupy/logic_sim.py index cddde47..70b3d18 100644 --- a/src/kyupy/logic_sim.py +++ b/src/kyupy/logic_sim.py @@ -22,40 +22,19 @@ class LogicSim: self.zero = np.zeros((mdim, nbytes), dtype='uint8') self.epoch = 0 - self.fork_vd1 = self.fork_vdx - 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}')] + known_fct = [(f[:-4], getattr(self, f)) for f in dir(self) if f.endswith(f'_fct')] self.node_fct = [] for n in circuit.nodes: 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('__const1__', '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)] if len(fcts) < 1: raise ValueError(f'Unknown node kind {n.kind}') @@ -90,7 +69,7 @@ class LogicSim: resp[...] = self.state[node.ins[0].index] # 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).""" for node in self.circuit.topological_order(): if self.state_epoch[node.index] != self.epoch: continue @@ -99,133 +78,61 @@ class LogicSim: # print('sim', node) self.node_fct[node.index](inputs, outputs) 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.epoch = (self.epoch + 1) % 128 - def fork_vdx(self, inputs, outputs): + @staticmethod + def fork_fct(inputs, outputs): for o in outputs: o[...] = inputs[0] - - def const0_vdx(self, _, outputs): - for o in outputs: o[...] = self.zero - - # 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): - self.or_vd1(inputs, outputs) - self.not_vd1(outputs, outputs) - def xnor_vd1(self, inputs, outputs): - self.xor_vd1(inputs, outputs) - self.not_vd1(outputs, outputs) + @staticmethod + def const0_fct(_, outputs): + for o in outputs: o[...] = 0 - # 4-valued simulation + @staticmethod + def const1_fct(_, outputs): + for o in outputs: + o[...] = 0 + logic.bp_not(o, o) - def not_vd2(self, inputs, outputs): + @staticmethod + def not_fct(inputs, outputs): 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) - def or_vd2(self, inputs, outputs): + @staticmethod + def or_fct(inputs, outputs): logic.bp_or(outputs[0], *inputs) - def xor_vd2(self, inputs, outputs): + @staticmethod + def xor_fct(inputs, outputs): logic.bp_xor(outputs[0], *inputs) - def sdff_vd2(self, inputs, outputs): - self.dff_vd2(inputs, outputs) + @staticmethod + def sdff_fct(inputs, outputs): + logic.bp_buf(outputs[0], inputs[0]) if len(outputs) > 1: 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]) - def nand_vd2(self, inputs, outputs): - self.and_vd2(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): + @staticmethod + def nand_fct(inputs, outputs): 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_not(outputs[0], outputs[0]) - def xor_vd3(self, inputs, outputs): + @staticmethod + def xnor_fct(inputs, outputs): logic.bp_xor(outputs[0], *inputs) - - 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) + logic.bp_not(outputs[0], outputs[0])