class TstScript():
    def __init__(self):
        self.logger = Logger()
        self.testName = None
        self.testHdlModule = None
        self.outputFile = None
        self.compareFile = None
        self.testChip = None
        self.outputFormatList = []
        self.setSequences = []
        return

    ##########################################################################
    def AddSetSequence(self, setSequence):
        self.setSequences.append(setSequence)
        return

    ##########################################################################
    def SetOutputFormatList(self, outputFormatList):
        self.outputFormatList = outputFormatList
        return

    ##########################################################################
    def GetOutputFormatList(self):
        return self.outputFormatList

    ##########################################################################
    def DumpTestDetails(self):
        self.logger.Debug("***** START: %s Test Script *****" %
                          (self.testName))
        self.logger.Debug("Test module:   %s" % (self.testHdlModule))
        self.logger.Debug("Output file:   %s" % (self.outputFile))
        self.logger.Debug("Compare file:  %s" % (self.compareFile))
        self.logger.Debug(
            "Output format: %s" %
            (', '.join([x.GetParamName() for x in self.outputFormatList])))

        sequenceNumber = 1
        for setSequence in self.setSequences:  #Type: TstSetSequence
            self.logger.Debug("  Sequence: %d" % (sequenceNumber))
            if setSequence.setOperation:
                self.logger.Debug("    Operation: %s = %s" %
                                  (setSequence.setOperation.pinName,
                                   setSequence.setOperation.pinValue))
            sequenceNumber += 1

        self.logger.Debug("***** END:   %s Test Script  *****" %
                          (self.testName))
        return
Beispiel #2
0
class H2VParamMappingList:
    def __init__(self):
        self.logger = Logger()
        self.verilogCallParams = VerilogCallParams()
        self.paramMappingList  = [] #type: list[H2VParamMappingItem]
        return

    ##########################################################################
    def AddItem(self, hdlStartBit, hdlEndBit, pinBitWdith, verilogParam):
        itemAdded       = False
        overlapDetected = False
        for item in self.paramMappingList:
            if hdlStartBit >= item.hdlStartBit and hdlEndBit <= item.hdlEndBit:
                overlapDetected = True
                break

        if not overlapDetected:
            self.paramMappingList.append(H2VParamMappingItem(hdlStartBit, hdlEndBit, pinBitWdith, verilogParam))
            itemAdded = True

        return itemAdded

    ##########################################################################
    def CompleteMapping(self, pin1, pin2, pin1BitWidth):
        numMappedBits = self._CountMappedBits(self.paramMappingList)
        if numMappedBits < pin1BitWidth:
            self.logger.Debug("Not enough bits mapped: %s to %s: Bit Width: %d, Mapped Bits: %d. Will add padding." % 
                                (pin1.pinName, pin2.pinName, pin1BitWidth, numMappedBits))
        
            self._PadMissingBits(pin1.pinName,
                                 pin2.pinName,
                                 pin1BitWidth, 
                                 self.paramMappingList, 
                                 True if pin1.pinType == HdlPinTypes.Output else False)

        newlist = sorted(self.paramMappingList, key=lambda x: x.vStartBit)
        for item in newlist:
            self.verilogCallParams.AddParam(item.verilogParam)
        #print(len(newlist))
        #self.verilogCallParams.DumpInfo()
        return

    ##########################################################################
    def GetVerilogParams(self): 
        return self.verilogCallParams
        
    ##########################################################################
    def _PadMissingBits(self, pin1Name, pin2Name, pinBitWidth, paramMappingList, isOutputPin):
        bitMapList = [0] * pinBitWidth

        for item in paramMappingList:
            for i in range(item.hdlStartBit, item.hdlEndBit + 1):
                bitMapList[i] = 1

        if isOutputPin:
            for i in range(0, pinBitWidth):
                if bitMapList[i] == 0:
                    paramMappingList.append(H2VParamMappingItem(i, i, pinBitWidth, "false")) 
        else:
            startPos = -1
            endPos   = -1
            for i in range(0, pinBitWidth):
                if startPos == -1 and bitMapList[i] == 0:
                    startPos = i
                if startPos != -1 and bitMapList[i] == 1:
                    endPos = i
                    width  = endPos - startPos
                    paramMappingList.append(H2VParamMappingItem(startPos, endPos, pinBitWidth, str(width) + "'b0")) 
                    startPos = -1
                    endPos   = -1

            if startPos != -1 and endPos == -1:
                width = pinBitWidth - startPos
                paramMappingList.append(H2VParamMappingItem(startPos, pinBitWidth - 1, pinBitWidth, str(width) + "'b0"))

        #print("%s --> %s: %s" % (pin1Name, pin2Name, bitMapList))
        return

    ##########################################################################
    def _CountMappedBits(self, paramMappingList):
        totalBits = 0
        for item in paramMappingList:
            totalBits += item.GetNumBits()
        return totalBits
Beispiel #3
0
class HdlToVerilogMapper():
    def __init__(self):
        self.logger = Logger()
        return

    ##########################################################################
    def CreateVerilogModuleTB(self, tstScript : TstScript, outputFolder):
        hdlChip       = tstScript.testChip # type: HDLChip
        verilogModGen = VerilogTestBenchGenerator(outputFolder)
        
        clkPinName = None
        clkPin     = hdlChip.GetClkPin()
        if clkPin:
            clkPinName = clkPin.pinName
            
        verilogModuleTB = VerilogModuleTB(tstScript.testName + "_tb",
                                          tstScript.testHdlModule,
                                          tstScript.testName + ".vcd",
                                          tstScript.outputFile,
                                          clkPinName)

        portList = []
        for inputPin in hdlChip.GetInputPinList(): #type: HdlPin
            portList.append(self._HdlPinToVerilogPort(inputPin, inputPin.GetPinBitWidth()))
        verilogModuleTB.AddInputPorts(portList)

        portList = []
        for outputPin in hdlChip.GetOutputPinList(): #type: HdlPin
            portList.append(self._HdlPinToVerilogPort(outputPin, outputPin.GetPinBitWidth()))
        verilogModuleTB.AddOutputPorts(portList)
        
        verilogModuleTB.AddOutputFormatList(tstScript.GetOutputFormatList())
        
        for setSequence in tstScript.setSequences: #type: TstSetSequence
            setOperation = None
            if setSequence.setOperation:
                setOperation = TstSetOperation(setSequence.setOperation.pinName, 
                                               self._HdlFormatToVerilogFormatLiteral(setSequence.setOperation.pinValue))

            verilogModuleTB.AddTestSequence(TstSetSequence(setSequence.sequenceType, setOperation))

        #verilogModuleTB.DumpModuleDetails()
        verilogModGen.CreateModule(verilogModuleTB)
        return

    ##########################################################################
    def CreateVerilogModule(self, hdlChip : HdlChip, hdlChipList : HdlChipList, verilogModuleList : VerilogModuleList):
        partList = hdlChip.GetChipPartList() #type: list[HdlChipPart]

        verilogMainModule = VerilogModule(hdlChip.chipName)

        portList = []
        for inputPin in hdlChip.GetInputPinList(): #type: HdlPin
            portList.append(self._HdlPinToVerilogPort(inputPin, inputPin.GetPinBitWidth()))
        verilogMainModule.AddInputPorts(portList)

        portList = []
        for outputPin in hdlChip.GetOutputPinList(): #type: HdlPin
            portList.append(self._HdlPinToVerilogPort(outputPin, outputPin.GetPinBitWidth()))
        verilogMainModule.AddOutputPorts(portList)

        tmpVarCounter        = 0
        verilogSubmoduleDict = {}
        for part in partList:
            self.logger.Debug("Mapping: Chip %s, Part %s (line %d)" % (hdlChip.chipName, part.partName, part.lineNo))
            connections = part.GetConnections() #type: list[HdlConnection]

            paramMapperDict = {}
            for connection in connections:
                pin1, pin2 = connection.GetPins() # type: HdlPin, HdlPin
              
                toPort   = self._HdlPinToVerilogPort(pin1, pin1.GetPinBitWidth())
                fromPort = self._HdlPinToVerilogPort(pin2, connection.pin2ConnectionWidth)

                keyName = pin1.pinName
                if keyName not in paramMapperDict:
                    paramMapperDict[keyName] = HdlToVerilogParamMapper(hdlChip.chipName, part.partName, part.lineNo, toPort, fromPort)         
                
                paramMapperDict[keyName].AddHdlConnection(connection)

            if part.partName not in verilogSubmoduleDict:
                verilogSubmoduleDict[part.partName] = 0
            else:
                verilogSubmoduleDict[part.partName] += 1

            verilogSubmoduleCall = VerilogSubmoduleCall(part.partName, verilogSubmoduleDict[part.partName])

            for paramMapper in paramMapperDict:
                paramMapperDict[paramMapper].DoMapping()

                toPort       = paramMapperDict[paramMapper].toPort
                fromPort     = paramMapperDict[paramMapper].fromPort
                mappedParams = paramMapperDict[paramMapper].GetMappedParams()

                numParamsForCall = mappedParams.GetNumParamsForCall()

                # Normal case: All parameters can be mapped onto a single input or output port
                if numParamsForCall == 1:
                    verilogSubmoduleCallParam = VerilogSubmoduleCallParam(toPort, fromPort, mappedParams.GetVerilogParams(0))
                    verilogSubmoduleCall.AddCallParam(verilogSubmoduleCallParam)

                # Multiple param case:
                # We can duplicate outputs in HDL mode calls, which isn't support in verilog. Therefore to map this case to verilog
                # we will have to assign the output pin to a new internal parameter and the use assign calls to set the correct ports.
                # e.g.
                # HDL:      Nand(a=a, b=b, out=out1, out=out2)
                # would map to..
                # Verilog:  Nand nand_1(.a (a), .b(b), .out(outTemp))
                #           assign out1 = outTemp;
                #           assign out2 = outTemp;
                else:
                    # Create the mapping to a new temporary internal parameter, which is the same width as the toPort
                    tmpPinName = ("tempOutput_%d" % (tmpVarCounter))
                    tmpPin     = HdlPin(tmpPinName, HdlPinTypes.Internal, None)
                    tmpPort    = self._HdlPinToVerilogPort(tmpPin, toPort.portBitWidth)

                    verilogSubmoduleCallParam = VerilogSubmoduleCallParam(toPort, tmpPort, VerilogCallParams(paramList=[tmpPort.portName]))
                    verilogSubmoduleCall.AddCallParam(verilogSubmoduleCallParam)
                    tmpVarCounter += 1

                    for i in range(0, numParamsForCall):
                        verilogMainModule.AddWireAssignment(VerilogWireAssignment(mappedParams.GetVerilogParams(i).GetCallStr(), tmpPinName))

            verilogMainModule.AddSubmoduleCall(verilogSubmoduleCall)

        verilogMainModule.DumpModuleDetails()
        verilogModuleList.AddModule(verilogMainModule)
        return

    ##########################################################################
    def _HdlFormatToVerilogFormatLiteral(self, hdlLiteral):
        verilogLiteral = hdlLiteral.replace("%B", "'b").replace("%X", "'h")
        return verilogLiteral

    ##########################################################################
    def _HdlPinToVerilogPort(self, hdlPin : HdlPin, bitWidth):
        portDirection = VerilogPortDirectionTypes.unknown

        if hdlPin.pinType == HdlPinTypes.Input or hdlPin.pinType == HdlPinTypes.Clk:
            portDirection = VerilogPortDirectionTypes.input
        elif hdlPin.pinType == HdlPinTypes.Output:
            portDirection = VerilogPortDirectionTypes.output

        return VerilogPort(hdlPin.pinName, portDirection, "", bitWidth, hdlPin.IsInternal())
class VerilogModuleTB():
    def __init__(self, moduleName, testModuleName, dumpFilename, outFilename,
                 clkPortName):
        self.logger = Logger()
        self.moduleName = moduleName
        self.testModuleName = testModuleName
        self.dumpFilename = dumpFilename
        self.outFilename = outFilename
        self.clkPortName = clkPortName
        self.inputPorts = []
        self.outputPorts = []
        self.outputFormats = []
        self.testSequences = []
        return

    ##########################################################################
    def AddInputPorts(self, inputs):
        self.logger.Debug("AddInputPorts: %d" % (len(inputs)))
        for inputPort in inputs:
            self.inputPorts.append(inputPort)
        return

    ##########################################################################
    def AddOutputPorts(self, outputs):
        self.logger.Debug("AddOutputPorts: %d" % (len(outputs)))
        for outputPort in outputs:
            self.outputPorts.append(outputPort)
        return

    ##########################################################################
    def AddOutputFormatList(self, outputFormatList):
        self.logger.Debug("AddOutputFormatList: %d" % (len(outputFormatList)))
        self.outputFormatList = outputFormatList
        return

    ##########################################################################
    def AddTestSequence(self, testSequence: TstSetSequence):
        self.testSequences.append(testSequence)
        return

    ##########################################################################
    def GetInputNameList(self):
        return [str(x.portName) for x in self.inputPorts]

    ##########################################################################
    def GetOutputNameList(self):
        return [str(x.portName) for x in self.outputPorts]

    ##########################################################################
    def GetInputPortList(self):
        return self.inputPorts

    ##########################################################################
    def GetOutputPortList(self):
        return self.outputPorts

    ##########################################################################
    def GetOutputFormatList(self):
        return self.outputFormatList

    ##########################################################################
    def GetOutputParamList(self):
        return [x for x in self.outputFormatList if x.GetParamName() != "time"]

    ##########################################################################
    def GetClkPortName(self):
        return self.clkPortName

    ##########################################################################
    def GetPortSignedStr(self, portName):
        signedStr = "signed"
        # HDL HardwareSimulator.sh treats certain params as unsigned if they
        # are specified as decimal. This is a hack to replicate that behaviour.
        if portName == "address" or portName == "sel":
            signedStr = "unsigned"

        return signedStr

    ##########################################################################
    def DumpModuleDetails(self):
        self.logger.Info("***** START: %s Verilog TestBench Module *****" %
                         (self.moduleName))
        self.logger.Info("Interface:")
        self.logger.Info("  Inputs:  %s" %
                         (', '.join(self.GetInputNameList())))
        self.logger.Info("  Outputs: %s" %
                         (', '.join(self.GetOutputNameList())))

        sequenceNumber = 1
        self.logger.Info("Test Steps:")
        for setSequence in self.testSequences:  #type: TstSetSequence
            self.logger.Info("  Test Step: %d" % (sequenceNumber))
            if setSequence.setOperations:
                for setOperation in setSequence.setOperations:  #type: TstSetOperation
                    self.logger.Info(
                        "    Operation: %s = %s" %
                        (setOperation.pinName, setOperation.pinValue))
            sequenceNumber += 1
        self.logger.Info("***** END: %s Verilog TestBench Module *****" %
                         (self.moduleName))
        return