#!/usr/bin/python -O """ # Galemu testcase generator # # Copyright (C) 2008 Michael Buesch # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . """ import sys from pdsparser import * import galemu class TestgenEx(Exception): pass class ChipState: def __init__(self, testgen): self.testgen = testgen self.testCounter = 0 # Init the input pin states self.inputs = {} for nr in testgen.galClass.getInputPinNumbers(): self.inputs[nr] = False # Init the output pin states # self.outputs = {} # for nr in testgen.galClass.getOutputPinNumbers(): # self.outputs[nr] = True def changeInputs(self, states): """Set some input signals to new states. Expects "states" as a dict of states { pinNumber : False|True, ... }""" for pinNr in states.keys(): self.inputs[pinNr] = states[pinNr] self.emitTestcase(emitInput=True) def validateOutputs(self, states): """Validate all output signals. Expects "states" as a dict of states { pinNumber : False|True, ...}""" # for pinNr in states.keys(): # self.outputs[pinNr] = states[pinNr] self.outputs = states self.emitTestcase(emitOutput=True) def emitTestcase(self, emitInput=False, emitOutput=False): self.testgen.addOutString("%d {\n" % self.testCounter) self.testCounter += 1 if emitInput: self.testgen.addOutString("\tINPUT\t") ip = self.inputs.keys()[:] ip.sort() for pinNr in ip: self.testgen.addOutString("%d=%d " % (pinNr, self.inputs[pinNr])) self.testgen.addOutString("\n") if emitOutput: self.testgen.addOutString("\tOUTPUT\t") op = self.outputs.keys()[:] op.sort() for pinNr in op: self.testgen.addOutString("%d=%d " % (pinNr, self.outputs[pinNr])) self.testgen.addOutString("\n") self.testgen.addOutString("}\n") class TestGen: def __init__(self, pdsText): self.pds = Pds(pdsText) if not self.pds.sim: raise TestgenEx(".PDS file does not contain a SIMULATION segment") if not self.pds.sim.getItems(): raise TestgenEx(".PDS file SIMULATION segment is empty") if not self.pds.chip: raise TestgenEx(".PDS file does not contain a CHIP declaration") try: self.galClass = galemu.selectGalClassObject(self.pds.chip[1]) except galemu.GalemuEx, e: raise TestgenEx(e.message) self.state = ChipState(self) def addOutString(self, text): self.out += text def sigs2str(self, sigs): text = "" for sig in sigs: if sig.inverted: text += "/" text += sig.name + " " return text def generateSimfile(self): self.genPinNumberDicts() # Generate the header self.out = "# Galemu testcase" if self.pds.title: self.out += " automatically generated from %s\n" % self.pds.title self.out += "# %s\n" % self.pds.chip[1] self.out += "\n" # Generate the testcases for item in self.pds.sim.getItems(): self.handleSimItem(item) return self.out def handleSimItem(self, item): "Handle a SimSeg().item" type = item[0] args = item[1:] if type == SimSeg.S_TRACE_ON: pass # Nothing elif type == SimSeg.S_TRACE_OFF: pass # Nothing elif type == SimSeg.S_SETF: self.out += "# SETF %s\n" % self.sigs2str(args) self.handleSetf(args) elif type == SimSeg.S_CHECK: self.out += "# CHECK %s\n" % self.sigs2str(args) self.handleCheck(args) elif type == SimSeg.S_PRELOAD: self.out += "# PRELOAD %s\n" % self.sigs2str(args) self.handlePreload(args) elif type == SimSeg.S_CLOCKF: self.out += "# CLOCKF %s\n" % self.sigs2str(args) self.handleClockf(args) else: raise TestgenEx("Internal error: Unknown SimSeg item type") def handleSetf(self, args): newStates = {} for sig in args: if sig.name not in self.inputMap: raise TestgenEx("SETF: Signal is not an input") pinNr = self.inputMap[sig.name] if sig.inverted: state = False else: state = True newStates[pinNr] = state self.state.changeInputs(newStates) def handleCheck(self, args): checkStates = {} for sig in args: if sig.name not in self.outputMap: #FIXME We ignore this for now #raise TestgenEx("CHECK: Signal not an output") continue pinNr = self.outputMap[sig.name] if sig.inverted: state = False else: state = True checkStates[pinNr] = state self.state.validateOutputs(checkStates) def handlePreload(self, args): pass#TODO def handleClockf(self, args): # Generate LOW-HIGH-LOW pulses. Use the setf subroutine. pulses = (False, True, False) for pulse in pulses: for sig in args: sig.inverted = not pulse self.handleSetf(args) def genPinNumberDicts(self): "Generate pinname-to-pinnumber dicts for input and output pins" inputs = self.galClass.getInputPinNumbers() outputs = self.galClass.getOutputPinNumbers() vcc = self.galClass.getVccPinNumber() gnd = self.galClass.getGndPinNumber() self.inputMap = {} self.outputMap = {} for pin in self.pds.pins: number = pin[0] name = pin[1] if number in inputs: self.inputMap[name] = number elif number in outputs: self.outputMap[name] = number elif number == vcc or number == gnd: pass # nothing else: raise TestgenEx("Pin %d is neither known as input nor output" % number) def main(argv): try: text = sys.stdin.read() gen = TestGen(text) text = gen.generateSimfile() sys.stdout.write(text) except PdsEx, e: raise TestgenEx(e.message) return 0 if __name__ == "__main__": try: sys.exit(main(sys.argv)) except TestgenEx, e: sys.stderr.write("[EXCEPTION]: " + e.message + "\n") sys.exit(1)