def __init__(self, *args, **kwargs): config = kwargs.pop('config', {}) ValidatedBusDriver.__init__(self, *args, **kwargs) self.config = AvalonSTPkts._default_config.copy() for configoption, value in config.items(): self.config[configoption] = value self.log.debug("Setting config option %s to %s" % (configoption, str(value))) word = BinaryValue(bits=len(self.bus.data), bigEndian=self.config['firstSymbolInHighOrderBits']) empty = BinaryValue(bits=len(self.bus.empty), bigEndian=False) single = BinaryValue(bits=1, bigEndian=False) word.binstr = ("x"*len(self.bus.data)) empty.binstr = ("x"*len(self.bus.empty)) single.binstr = ("x") self.bus.valid <= 0 self.bus.data <= word self.bus.empty <= empty self.bus.startofpacket <= single self.bus.endofpacket <= single
def __init__(self, *args, **kwargs): config = kwargs.pop('config', {}) ValidatedBusDriver.__init__(self, *args, **kwargs) self.config = AvalonSTPkts._default_config.copy() for configoption, value in config.items(): self.config[configoption] = value self.log.debug("Setting config option %s to %s" % (configoption, str(value))) word = BinaryValue(bits=len(self.bus.data), bigEndian=self.config['firstSymbolInHighOrderBits']) empty = BinaryValue(bits=len(self.bus.empty), bigEndian=False) single = BinaryValue(bits=1, bigEndian=False) word.binstr = ("x" * len(self.bus.data)) empty.binstr = ("x" * len(self.bus.empty)) single.binstr = ("x") self.bus.valid <= 0 self.bus.data <= word self.bus.empty <= empty self.bus.startofpacket <= single self.bus.endofpacket <= single
async def random_wires(dut): """ Test simple wires logic with random bits """ for i in range(10000): # Create random values to send to model and dut # Random int value with max 3 bits. unsigned. random_dec_value_a = random.randint(0, 7) random_dec_value_b = random.randint(0, 7) # Convert random decimal to a string to represnt binary. a_binary = f'{random_dec_value_a:03b}' b_binary = f'{random_dec_value_b:03b}' # Convert to cocotb structure BinaryValue, 3 bits long. a_bin_cocotb = BinaryValue(n_bits=3) a_bin_cocotb.binstr = a_binary b_bin_cocotb = BinaryValue(n_bits=3) b_bin_cocotb.binstr = b_binary # Send random values to dut dut.a <= int(random_dec_value_a) dut.b <= int(random_dec_value_b) # Wait for dut to do its thing await Timer(1, units='ns') # Get values from DUT dut_out_or_bitwise = BinaryValue(n_bits=3) dut_out_or_bitwise = dut.out_or_bitwise.value # Skipped converting || from verilog. It just tests if both values are 0. #dut_out_or_logical = BinaryValue(n_bits=1) #dut_out_or_logical = dut.out_or_logical.value dut_out_not = BinaryValue(n_bits=6) dut_out_not = dut.out_not.value # Python Model python_bitwise = a_bin_cocotb | b_bin_cocotb python_not = ~b_bin_cocotb + ~a_bin_cocotb print("-----------------------------------------") print("Test ", i) print("Input value a ", a_binary) print("Input value b ", b_binary) print("DUT Output dut.out_or_bitwise.value ", dut.out_or_bitwise.value) print("DUT Output dut.out_not.value ", dut.out_not.value) print("-----------------------------------------\n") # Compare results if int(dut.out_or_bitwise.value) != python_bitwise: raise cocotb.result.TestFailure( "DUT recorded %d value but model recorded %d" % (int(dut.out_or_bitwise.value), python_bitwise)) if str(dut.out_not.value) != python_not: raise cocotb.result.TestFailure( "DUT recorded %d value but model recorded %d" % (str(dut.out_not.value), python_not))
def PHVDeparser(busSize, PHV, payload=None): """ model for the packet deparser From a PHV return an ordered list of expected output stream PHV : full binary value of headers busSize : width of the output bus in bits payload : Binary value of packet """ stream = [] if payload is not None: pkt = BinaryValue("{}{}".format(PHV.binstr, payload.binstr)) print(pkt) else: pkt = PHV nbFrame = ceil(len(pkt.binstr) / busSize) end = 0 start = 0 if nbFrame > 1: for i in range(nbFrame - 1): start = end end = start + busSize val = BinaryValue(n_bits=busSize) val.binstr = pkt.binstr[start:end] stream.append(val) start = end end = len(pkt.binstr) size = end - start val = BinaryValue(0, n_bits=size) if size != len(pkt.binstr): val.binstr = pkt.binstr[start:end] else: val.binstr = pkt.binstr[start:end] stream.append(val) return stream
def __init__(self, entity, name, clock, *, config={}, **kwargs): ValidatedBusDriver.__init__(self, entity, name, clock, **kwargs) self.config = AvalonSTPkts._default_config.copy() # Set default config maxChannel to max value on channel bus if hasattr(self.bus, 'channel'): self.config['maxChannel'] = (2**len(self.bus.channel)) - 1 for configoption, value in config.items(): self.config[configoption] = value self.log.debug("Setting config option %s to %s", configoption, str(value)) num_data_symbols = (len(self.bus.data) / self.config["dataBitsPerSymbol"]) if (num_data_symbols > 1 and not hasattr(self.bus, 'empty')): raise AttributeError( "%s has %i data symbols, but contains no object named empty" % (self.name, num_data_symbols)) self.use_empty = (num_data_symbols > 1) self.config["useEmpty"] = self.use_empty word = BinaryValue(n_bits=len(self.bus.data), bigEndian=self.config["firstSymbolInHighOrderBits"]) single = BinaryValue(n_bits=1, bigEndian=False) word.binstr = "x" * len(self.bus.data) single.binstr = "x" self.bus.valid.value = 0 self.bus.data.value = word self.bus.startofpacket.value = single self.bus.endofpacket.value = single if self.use_empty: empty = BinaryValue(n_bits=len(self.bus.empty), bigEndian=False, value="x" * len(self.bus.empty)) self.bus.empty.value = empty if hasattr(self.bus, 'channel'): if len(self.bus.channel) > 128: raise AttributeError( "Avalon-ST interface specification defines channel width as 1-128. " "%d channel width is %d" % (self.name, len(self.bus.channel))) maxChannel = (2**len(self.bus.channel)) - 1 if self.config['maxChannel'] > maxChannel: raise AttributeError( "%s has maxChannel=%d, but can only support a maximum channel of " "(2**channel_width)-1=%d, channel_width=%d" % (self.name, self.config['maxChannel'], maxChannel, len(self.bus.channel))) channel = BinaryValue(n_bits=len(self.bus.channel), bigEndian=False, value="x" * len(self.bus.channel)) self.bus.channel.value = channel
def __init__(self, *args, **kwargs): config = kwargs.pop('config', {}) ValidatedBusDriver.__init__(self, *args, **kwargs) self.config = AvalonSTPkts._default_config.copy() # Set default config maxChannel to max value on channel bus if hasattr(self.bus, 'channel'): self.config['maxChannel'] = (2 ** len(self.bus.channel)) -1 for configoption, value in config.items(): self.config[configoption] = value self.log.debug("Setting config option %s to %s" % (configoption, str(value))) num_data_symbols = (len(self.bus.data) / self.config["dataBitsPerSymbol"]) if (num_data_symbols > 1 and not hasattr(self.bus, 'empty')): raise AttributeError( "%s has %i data symbols, but contains no object named empty" % (self.name, num_data_symbols)) self.use_empty = (num_data_symbols > 1) self.config["useEmpty"] = self.use_empty word = BinaryValue(n_bits=len(self.bus.data), bigEndian=self.config['firstSymbolInHighOrderBits']) single = BinaryValue(n_bits=1, bigEndian=False) word.binstr = ("x"*len(self.bus.data)) single.binstr = ("x") self.bus.valid <= 0 self.bus.data <= word self.bus.startofpacket <= single self.bus.endofpacket <= single if self.use_empty: empty = BinaryValue(n_bits=len(self.bus.empty), bigEndian=False) empty.binstr = ("x"*len(self.bus.empty)) self.bus.empty <= empty if hasattr(self.bus, 'channel'): if len(self.bus.channel) > 128: raise AttributeError( "Avalon-ST interface specification defines channel width as 1-128. %d channel width is %d" % (self.name, len(self.bus.channel)) ) maxChannel = (2 ** len(self.bus.channel)) -1 if self.config['maxChannel'] > maxChannel: raise AttributeError( "%s has maxChannel=%d, but can only support a maximum channel of (2**channel_width)-1=%d, channel_width=%d" % (self.name,self.config['maxChannel'],maxChannel,len(self.bus.channel))) channel = BinaryValue(n_bits=len(self.bus.channel), bigEndian=False) channel.binstr = ("x"*len(self.bus.channel)) self.bus.channel <= channel
def __init__(self, entity, name, clock): BusDriver.__init__(self, entity, name, clock) word = BinaryValue(bits=32) single = BinaryValue(bits=1) word.binstr = ("x" * 32) single.binstr = ("x") self.bus.load_i <= single self.bus.rst_i <= single self.bus.dat_i <= word
async def random_wires(dut): """ Test simple wires logic with random bits """ for i in range(10000): # Create random values to send to model and dut # Random int value with max 32 bits. unsigned. random_dec_value = random.randint(0, 4294967295) # Convert random decimal to a string to represnt binary. a_binary = f'{random_dec_value:032b}' # Convert to cocotb structure BinaryValue, 32 bits long. a_bin_cocotb = BinaryValue(n_bits=32) a_bin_cocotb.binstr = a_binary # Set high and low values to compare with the DUT # Byte order seems to be reverse from VHDL a_bin_cocotb_byte_0 = str(a_bin_cocotb[0:7]) # Left most value (MSB) a_bin_cocotb_byte_1 = str(a_bin_cocotb[8:15]) a_bin_cocotb_byte_2 = str(a_bin_cocotb[16:23]) a_bin_cocotb_byte_3 = str( a_bin_cocotb[24:31]) # Right most value (LSB) # Send random values to dut dut.vec <= int(random_dec_value) # Wait for dut to do its thing await Timer(1, units='ns') # Get values from DUT dut_outvec = BinaryValue(n_bits=32) dut_outvec = dut.outvec.value print("---------------------------------") print("Test ", i) print("Input value ", a_binary) print("DUT Output dut.outvec.value ", dut.outvec.value) print("---------------------------------\n") # Compare results if str(dut.outvec.value[24:31]) != a_bin_cocotb_byte_0: raise cocotb.result.TestFailure( "DUT recorded %d value but model recorded %d" % (int(dut.outvec.value[24:31]), a_bin_cocotb_byte_0)) if str(dut.outvec.value[16:23]) != a_bin_cocotb_byte_1: raise cocotb.result.TestFailure( "DUT recorded %d value but model recorded %d" % (int(dut.outvec.value[16:23]), a_bin_cocotb_byte_1)) if str(dut.outvec.value[8:15]) != a_bin_cocotb_byte_2: raise cocotb.result.TestFailure( "DUT recorded %d value but model recorded %d" % (int(dut.outvec.value[8:15]), a_bin_cocotb_byte_2)) if str(dut.outvec.value[0:7]) != a_bin_cocotb_byte_3: raise cocotb.result.TestFailure( "DUT recorded %d value but model recorded %d" % (int(dut.outvec.value[0:7]), a_bin_cocotb_byte_3))
def _send_binary_string(self, pkt): """ Send string based information """ self.log.debug("sending packet: {}".format(pkt)) value = BinaryValue(n_bits=self.width, bigEndian=False) nb_frame = ceil(len(pkt) / (self.width / 8)) end = 0 if nb_frame > 1: for i in range(nb_frame - 1): start = int(ceil(i * (self.width / 8))) end = int(ceil((i + 1) * (self.width / 8))) self.log.debug("index start:{}, end:{}".format(start, end)) value.binstr = BitArray(pkt[start:end][::-1], len=self.width).bin self.log.debug("sending value:{}".format(pkt[start:end])) yield self._send_frame(value) value.binstr = BitArray(pkt[end:][::-1], len=self.width).bin self.log.debug("sending value:{}".format(pkt[end:])) keep = (1 << len(pkt[end:])) - 1 self.log.debug("sending keep:{:x}".format(keep)) yield self._send_frame(value, 1, keep)
def _driver_send(self, value, sync=True): """Send a transmission over the bus. Args: value: data to drive onto the bus. """ self.log.debug("Sending Avalon transmission: %r", value) # Avoid spurious object creation by recycling clkedge = RisingEdge(self.clock) word = BinaryValue(n_bits=len(self.bus.data), bigEndian=False) # Drive some defaults since we don't know what state we're in self.bus.valid <= 0 if sync: yield clkedge # Insert a gap where valid is low if not self.on: self.bus.valid <= 0 for _ in range(self.off): yield clkedge # Grab the next set of on/off values self._next_valids() # Consume a valid cycle if self.on is not True and self.on: self.on -= 1 self.bus.valid <= 1 word.assign(value) self.bus.data <= word # If this is a bus with a ready signal, wait for this word to # be acknowledged if hasattr(self.bus, "ready"): yield self._wait_ready() yield clkedge self.bus.valid <= 0 word.binstr = "x" * len(self.bus.data) self.bus.data <= word self.log.debug("Successfully sent Avalon transmission: %r", value)
def _driver_send(self, value, sync=True): """Send a transmission over the bus. Args: value: data to drive onto the bus. """ self.log.debug("Sending Avalon transmission: %d" % value) # Avoid spurious object creation by recycling clkedge = RisingEdge(self.clock) word = BinaryValue(n_bits=len(self.bus.data), bigEndian=False) # Drive some defaults since we don't know what state we're in self.bus.valid <= 0 if sync: yield clkedge # Insert a gap where valid is low if not self.on: self.bus.valid <= 0 for i in range(self.off): yield clkedge # Grab the next set of on/off values self._next_valids() # Consume a valid cycle if self.on is not True and self.on: self.on -= 1 self.bus.valid <= 1 word.assign(value) self.bus.data <= word # If this is a bus with a ready signal, wait for this word to # be acknowledged if hasattr(self.bus, "ready"): yield self._wait_ready() yield clkedge self.bus.valid <= 0 word.binstr = ("x"*len(self.bus.data)) self.bus.data <= word self.log.debug("Successfully sent Avalon transmission: %d" % value)
async def random_wires(dut): """ Test simple wires logic with random bits """ for i in range(10000): # Create random values to send to model and dut # Random int value with max 16 bits. unsigned. random_dec_value = random.randint(0, 65536) # Convert random decimal to a string to represnt binary. a_binary = f'{random_dec_value:016b}' # Convert to cocotb structure BinaryValue, 16 bits long. a_bin_cocotb = BinaryValue(n_bits=16) a_bin_cocotb.binstr = a_binary # Set high and low values to compare with the DUT a_bin_cocotb_hi = str(a_bin_cocotb[0:7]) a_bin_cocotb_lo = str(a_bin_cocotb[8:15]) # Send random values to dut dut.vec <= int(random_dec_value) # Wait for dut to do its thing await Timer(1, units='ns') # Get values from DUT dut_out_hi = BinaryValue(n_bits=16) dut_out_hi = dut.out_hi.value dut_out_lo = BinaryValue(n_bits=16) dut_out_lo = dut.out_lo.value print("---------------------------------") print("Test ", i) print("Input value ", a_binary) print("DUT Output dut.out_hi.value ", dut.out_hi.value) print("DUT Output dut.out_lo.value ", dut.out_lo.value) print("---------------------------------\n") # Compare results if str(dut.out_hi.value) != a_bin_cocotb_hi: raise cocotb.result.TestFailure( "DUT recorded %d value but model recorded %d" % (int(dut.out_hi.value), a_bin_cocotb_hi)) if str(dut.out_lo.value) != a_bin_cocotb_lo: raise cocotb.result.TestFailure( "DUT recorded %d value but model recorded %d" % (int(dut.out_lo.value), a_bin_cocotb_lo))
def driver_tx_rx(self): highZ = BinaryValue() highZ.binstr = "zzzzzzzz" while True: if (len(self.tx_fifo) < TX_FIFO_MAX): self.dut.txe_245 <= 0 else: self.dut.txe_245 <= 1 if (len(self.rx_fifo) > 0): self.dut.rxf_245 <= 0 else: self.dut.rxf_245 <= 1 if (self.dut.txe_245.value.integer == 0 and self.dut.wr_245.value.integer == 0): self.dut.rxf_245 <= 1 # TX --> then NOT RX # start tx sequence self.dut.in_out_245 <= highZ yield Timer(1, units='ps') self.tx_fifo.append(self.dut.in_out_245.value.integer) #print ("FDTI TX: " + repr(self.dut.in_out_245.value.integer)) yield nsTimer(14 + WR_TO_INACTIVE) #T6+... if (self.dut.wr_245.value.integer == 0): yield RisingEdge(self.dut.wr_245) self.dut.txe_245 <= 1 yield nsTimer(TXE_INACTIVE) else: if (self.dut.rxf_245.value.integer == 0 and self.dut.rx_245.value.integer == 0): self.dut.txe_245 <= 1 # RX --> then NOT TX yield Timer(1, units='ps') yield nsTimer(RD_TO_DATA) aux = self.rx_fifo.pop(0) self.dut.in_out_245 <= aux #self.rx_fifo.pop(0) #print "AUX = " + repr(aux) yield Timer(1, units='ps') if (self.dut.rx_245.value.integer == 0): yield RisingEdge(self.dut.rx_245) yield nsTimer(14) self.dut.rxf_245 <= 1 yield nsTimer(RFX_INACTIVE) else: yield Timer(10, units='ns')
def tx_monitor(self): vec = BinaryValue() vec.binstr = "zzzzzzzz" print("-----------------------------------------------") yield nsTimer(TXE_INACTIVE) while True: if True: self.dut.txe_245 <= 0 if self.dut.wr_245.value.integer == 1: yield FallingEdge(self.dut.wr_245) self.dut.in_out_245 <= vec yield Timer(1, units='ps') #print ("{WR_245, TXE_245} = " + repr(self.dut.wr_245.value.integer) + repr(self.dut.txe_245.value.integer) ) aux = self.dut.in_out_245.value.integer #aux = 0xAA self.tx_fifo.append(aux) print("FDTI TX: " + repr(aux)) yield nsTimer(WR_TO_INACTIVE) self.dut.txe_245 <= 1 yield nsTimer(TXE_INACTIVE)
def PacketParser(dut: cocotb.handle, packet: scapy_packet, scapy_to_VHDL): """setUp interface of dut with packet info If process header recursively, if not on dut raise error. This function is the expected output of a packet parser """ if not isinstance(packet, scapy_packet): raise TypeError("expected scapy Packet type") dut._log.info("debut parsage") for i in scapy_to_VHDL: signal_en = "{}_valid".format(scapy_to_VHDL[i][0]) if signal_en in dut._sub_handles: dut._sub_handles[signal_en].value = 0 if packet.haslayer(i): signal = "{}_bus".format(scapy_to_VHDL[i][0]) if not (signal in dut._sub_handles): raise ValueError("unvalid header : {}".format(signal)) val = BinaryValue() signal_width = int(scapy_to_VHDL[i][1] / 8) val.binstr = BitArray(raw(packet.getlayer(i))[0:signal_width]).bin val.buff = val.buff[::-1] dut._sub_handles[signal].value = val dut._sub_handles[signal_en].value = 1 dut._log.info("fin parser")
def _send_string(self, string, sync=True, channel=None): """Args: string (str): A string of bytes to send over the bus. channel (int): Channel to send the data on. """ # Avoid spurious object creation by recycling clkedge = RisingEdge(self.clock) firstword = True # FIXME busses that aren't integer numbers of bytes bus_width = int(len(self.bus.data) / 8) word = BinaryValue(n_bits=len(self.bus.data), bigEndian=self.config['firstSymbolInHighOrderBits']) single = BinaryValue(n_bits=1, bigEndian=False) if self.use_empty: empty = BinaryValue(n_bits=len(self.bus.empty), bigEndian=False) # Drive some defaults since we don't know what state we're in if self.use_empty: self.bus.empty <= 0 self.bus.startofpacket <= 0 self.bus.endofpacket <= 0 self.bus.valid <= 0 if hasattr(self.bus, 'error'): self.bus.error <= 0 if hasattr(self.bus, 'channel'): self.bus.channel <= 0 elif channel is not None: raise TestError("%s does not have a channel signal" % self.name) while string: if not firstword or (firstword and sync): yield clkedge # Insert a gap where valid is low if not self.on: self.bus.valid <= 0 for i in range(self.off): yield clkedge # Grab the next set of on/off values self._next_valids() # Consume a valid cycle if self.on is not True and self.on: self.on -= 1 self.bus.valid <= 1 if hasattr(self.bus, 'channel'): if channel is None: self.bus.channel <= 0 elif channel > self.config['maxChannel'] or channel < 0: raise TestError( "%s: Channel value %d is outside range 0-%d" % (self.name,channel,self.config['maxChannel'])) else: self.bus.channel <= channel if firstword: self.bus.startofpacket <= 1 firstword = False else: self.bus.startofpacket <= 0 nbytes = min(len(string), bus_width) data = string[:nbytes] word.buff = data if len(string) <= bus_width: self.bus.endofpacket <= 1 if self.use_empty: self.bus.empty <= bus_width - len(string) string = "" else: string = string[bus_width:] self.bus.data <= word # If this is a bus with a ready signal, wait for this word to # be acknowledged if hasattr(self.bus, "ready"): yield self._wait_ready() yield clkedge self.bus.valid <= 0 self.bus.endofpacket <= 0 word.binstr = ("x"*len(self.bus.data)) single.binstr = ("x") self.bus.data <= word self.bus.startofpacket <= single self.bus.endofpacket <= single if self.use_empty: empty.binstr = ("x"*len(self.bus.empty)) self.bus.empty <= empty if hasattr(self.bus, 'channel'): channel_value = BinaryValue(n_bits=len(self.bus.channel), bigEndian=False) channel_value.binstr = ("x"*len(self.bus.channel)) self.bus.channel <= channel_value
def _send_string(self, string, sync=True): """ Args: string (str): A string of bytes to send over the bus """ # Avoid spurious object creation by recycling clkedge = RisingEdge(self.clock) firstword = True # FIXME busses that aren't integer numbers of bytes bus_width = int(len(self.bus.data) / 8) word = BinaryValue(bits=len(self.bus.data), bigEndian=self.config['firstSymbolInHighOrderBits']) empty = BinaryValue(bits=len(self.bus.empty), bigEndian=False) single = BinaryValue(bits=1, bigEndian=False) # Drive some defaults since we don't know what state we're in # self.bus.empty <= 0 self.bus.startofpacket <= 0 self.bus.endofpacket <= 0 self.bus.valid <= 0 if hasattr(self.bus, 'error'): self.bus.error <= 0 while string: if not firstword or (firstword and sync): yield clkedge # Insert a gap where valid is low if not self.on: self.bus.valid <= 0 for i in range(self.off): yield clkedge # Grab the next set of on/off values self._next_valids() # Consume a valid cycle if self.on is not True and self.on: self.on -= 1 self.bus.valid <= 1 if firstword: #self.bus.empty <= 0 self.bus.startofpacket <= 1 firstword = False else: self.bus.startofpacket <= 0 nbytes = min(len(string), bus_width) data = string[:nbytes] word.buff = data if len(string) <= bus_width: self.bus.endofpacket <= 1 self.bus.empty <= bus_width - len(string) string = "" else: string = string[bus_width:] self.bus.data <= word # If this is a bus with a ready signal, wait for this word to # be acknowledged if hasattr(self.bus, "ready"): yield self._wait_ready() yield clkedge self.bus.valid <= 0 self.bus.endofpacket <= 0 word.binstr = ("x"*len(self.bus.data)) empty.binstr = ("x"*len(self.bus.empty)) single.binstr = ("x") self.bus.data <= word self.bus.empty <= empty self.bus.startofpacket <= single self.bus.endofpacket <= single
def getvalue(self): result = BinaryValue() result.binstr = self._get_value_str() return result
def scapy_to_BinaryValue(pkt): """ take scapy packet as input, return binaryvalue """ pkt_buf = BinaryValue() pkt_buf.binstr = BitArray(raw(pkt)).bin return pkt_buf
def _send_string(self, string, sync=True, channel=None): """Args: string (str): A string of bytes to send over the bus. channel (int): Channel to send the data on. """ # Avoid spurious object creation by recycling clkedge = RisingEdge(self.clock) firstword = True # FIXME: buses that aren't an integer numbers of bytes bus_width = int(len(self.bus.data) / 8) word = BinaryValue(n_bits=len(self.bus.data), bigEndian=self.config["firstSymbolInHighOrderBits"]) single = BinaryValue(n_bits=1, bigEndian=False) if self.use_empty: empty = BinaryValue(n_bits=len(self.bus.empty), bigEndian=False) # Drive some defaults since we don't know what state we're in if self.use_empty: self.bus.empty <= 0 self.bus.startofpacket <= 0 self.bus.endofpacket <= 0 self.bus.valid <= 0 if hasattr(self.bus, 'error'): self.bus.error <= 0 if hasattr(self.bus, 'channel'): self.bus.channel <= 0 elif channel is not None: raise TestError("%s does not have a channel signal" % self.name) while string: if not firstword or (firstword and sync): yield clkedge # Insert a gap where valid is low if not self.on: self.bus.valid <= 0 for _ in range(self.off): yield clkedge # Grab the next set of on/off values self._next_valids() # Consume a valid cycle if self.on is not True and self.on: self.on -= 1 self.bus.valid <= 1 if hasattr(self.bus, 'channel'): if channel is None: self.bus.channel <= 0 elif channel > self.config['maxChannel'] or channel < 0: raise TestError( "%s: Channel value %d is outside range 0-%d" % (self.name, channel, self.config['maxChannel'])) else: self.bus.channel <= channel if firstword: self.bus.startofpacket <= 1 firstword = False else: self.bus.startofpacket <= 0 nbytes = min(len(string), bus_width) data = string[:nbytes] word.buff = data if len(string) <= bus_width: self.bus.endofpacket <= 1 if self.use_empty: self.bus.empty <= bus_width - len(string) string = "" else: string = string[bus_width:] self.bus.data <= word # If this is a bus with a ready signal, wait for this word to # be acknowledged if hasattr(self.bus, "ready"): yield self._wait_ready() yield clkedge self.bus.valid <= 0 self.bus.endofpacket <= 0 word.binstr = "x" * len(self.bus.data) single.binstr = "x" self.bus.data <= word self.bus.startofpacket <= single self.bus.endofpacket <= single if self.use_empty: empty.binstr = "x" * len(self.bus.empty) self.bus.empty <= empty if hasattr(self.bus, 'channel'): channel_value = BinaryValue(n_bits=len(self.bus.channel), bigEndian=False, value="x" * len(self.bus.channel)) self.bus.channel <= channel_value
def _getvalue(self): result = BinaryValue() result.binstr = simulator.get_signal_val_binstr(self._handle) return result
def _send_string(self, string, sync=True): """ Args: string (str): A string of bytes to send over the bus """ # Avoid spurious object creation by recycling clkedge = RisingEdge(self.clock) firstword = True # FIXME busses that aren't integer numbers of bytes bus_width = int(len(self.bus.data) / 8) word = BinaryValue(bits=len(self.bus.data), bigEndian=self.config['firstSymbolInHighOrderBits']) empty = BinaryValue(bits=len(self.bus.empty), bigEndian=False) single = BinaryValue(bits=1, bigEndian=False) # Drive some defaults since we don't know what state we're in # self.bus.empty <= 0 self.bus.startofpacket <= 0 self.bus.endofpacket <= 0 self.bus.valid <= 0 if hasattr(self.bus, 'error'): self.bus.error <= 0 while string: if not firstword or (firstword and sync): yield clkedge # Insert a gap where valid is low if not self.on: self.bus.valid <= 0 for i in range(self.off): yield clkedge # Grab the next set of on/off values self._next_valids() # Consume a valid cycle if self.on is not True and self.on: self.on -= 1 self.bus.valid <= 1 if firstword: #self.bus.empty <= 0 self.bus.startofpacket <= 1 firstword = False else: self.bus.startofpacket <= 0 nbytes = min(len(string), bus_width) data = string[:nbytes] word.buff = data if len(string) <= bus_width: self.bus.endofpacket <= 1 self.bus.empty <= bus_width - len(string) string = "" else: string = string[bus_width:] self.bus.data <= word # If this is a bus with a ready signal, wait for this word to # be acknowledged if hasattr(self.bus, "ready"): yield self._wait_ready() yield clkedge self.bus.valid <= 0 self.bus.endofpacket <= 0 word.binstr = ("x" * len(self.bus.data)) empty.binstr = ("x" * len(self.bus.empty)) single.binstr = ("x") self.bus.data <= word self.bus.empty <= empty self.bus.startofpacket <= single self.bus.endofpacket <= single