112855Sgabeblack@google.com"""
212855Sgabeblack@google.com/*****************************************************************************
312855Sgabeblack@google.com
412855Sgabeblack@google.com  Licensed to Accellera Systems Initiative Inc. (Accellera) under one or
512855Sgabeblack@google.com  more contributor license agreements.  See the NOTICE file distributed
612855Sgabeblack@google.com  with this work for additional information regarding copyright ownership.
712855Sgabeblack@google.com  Accellera licenses this file to you under the Apache License, Version 2.0
812855Sgabeblack@google.com  (the "License"); you may not use this file except in compliance with the
912855Sgabeblack@google.com  License.  You may obtain a copy of the License at
1012855Sgabeblack@google.com
1112855Sgabeblack@google.com    http://www.apache.org/licenses/LICENSE-2.0
1212855Sgabeblack@google.com
1312855Sgabeblack@google.com  Unless required by applicable law or agreed to in writing, software
1412855Sgabeblack@google.com  distributed under the License is distributed on an "AS IS" BASIS,
1512855Sgabeblack@google.com  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
1612855Sgabeblack@google.com  implied.  See the License for the specific language governing
1712855Sgabeblack@google.com  permissions and limitations under the License.
1812855Sgabeblack@google.com
1912855Sgabeblack@google.com *****************************************************************************/
2012855Sgabeblack@google.com
2112855Sgabeblack@google.comPython Script to test Endianness Conversion Functions for OSCI TLM-2
2212855Sgabeblack@google.com
2312855Sgabeblack@google.comThere is a simple testbench programme in C++ which runs a single
2412855Sgabeblack@google.comtransaction through a single conversion function, to a simple target
2512855Sgabeblack@google.commemory and back.  This script will run the testbench many times and test for
2612855Sgabeblack@google.com- incomplete execution, seg-faults, etc
2712855Sgabeblack@google.com- distributability of conversion function: each transaction should have
2812855Sgabeblack@google.comthe same effect on initiator/target memory as a set of smaller transactions
2912855Sgabeblack@google.comthat sum to it
3012855Sgabeblack@google.com- equivalence: all conversion functions should have the same functional
3112855Sgabeblack@google.comeffect as each other
3212855Sgabeblack@google.com
3312855Sgabeblack@google.comThe approach is to provide the initial state of the initiator and
3412855Sgabeblack@google.comtarget memory (as strings) and to capture their final states, so that
3512855Sgabeblack@google.comonly the effect of the transaction on the data buffers is measured.
3612855Sgabeblack@google.com
3712855Sgabeblack@google.comScript works out for itself which conversion functions are legal for a
3812855Sgabeblack@google.comgiven transaction and applies all of them.  Note that where data is
3912855Sgabeblack@google.comwider than bus, only one conversion function is legal and testing is
4012855Sgabeblack@google.comsomewhat limited.
4112855Sgabeblack@google.com
4212855Sgabeblack@google.comTesting space (select a transaction at random from the space):
4312855Sgabeblack@google.com- with and without byte-enables (generated at random for each data word
4412855Sgabeblack@google.comand can be all-zero)
4512855Sgabeblack@google.com- data widths of (1,2,4,8,16)
4612855Sgabeblack@google.com- bus widths of (1,2,4,8,16), lower priority for those smaller than data
4712855Sgabeblack@google.comwidth
4812855Sgabeblack@google.com- transaction lengths of (1..32) x data width, higher probability for
4912855Sgabeblack@google.comlower values
5012855Sgabeblack@google.com- base address (0..1023) at bus_width steps
5112855Sgabeblack@google.com- offset address (0..bus width) with a higher priority for 0
5212855Sgabeblack@google.com- address in initiator buffer uniform random
5312855Sgabeblack@google.com- read or write
5412855Sgabeblack@google.com- byte-enable length may be smaller than transasction length
5512855Sgabeblack@google.com- may be a streaming burst
5612855Sgabeblack@google.com
5712855Sgabeblack@google.comTransaction breakdown
5812855Sgabeblack@google.com- individual words (always)
5912855Sgabeblack@google.com- one random breakdown with each segment containing between 1 and N-1
6012855Sgabeblack@google.comwords, where N is the length in words
6112855Sgabeblack@google.com- one breakdown with two segments interleaved, using (additional) byte
6212855Sgabeblack@google.comenables to suppress the part where the other segment is active
6312855Sgabeblack@google.com
6412855Sgabeblack@google.comData buffer definition:  starts at 0, randomly filled
6512855Sgabeblack@google.comwith lower case letters and numbers.  Size 2 kB.  Addresses are limited to
6612855Sgabeblack@google.com1 kB.
6712855Sgabeblack@google.com"""
6812855Sgabeblack@google.com
6912855Sgabeblack@google.com
7012855Sgabeblack@google.comimport random
7112855Sgabeblack@google.comimport string
7212855Sgabeblack@google.com
7312855Sgabeblack@google.com
7412855Sgabeblack@google.comclass transaction:
7512855Sgabeblack@google.com  """ contains read_not_write, address, length, byte_enable,
7612855Sgabeblack@google.com      bus_width, data_width, data_pointer, stream_width """
7712855Sgabeblack@google.com  def __init__(self, **a):  self.__dict__ = a
7812855Sgabeblack@google.com  def __str__(self):
7912855Sgabeblack@google.com    if self.read_not_write:  a = "R: "
8012855Sgabeblack@google.com    else:  a = "W: "
8112855Sgabeblack@google.com    a += "addr = %d, len = %d, bus = %d, word = %d, data = %d" % \
8212855Sgabeblack@google.com      (self.address, self.length, self.bus_width, self.data_width, \
8312855Sgabeblack@google.com       self.data_pointer)
8412855Sgabeblack@google.com    if self.byte_enable:  a += ", be = " + self.byte_enable
8512855Sgabeblack@google.com    else:  a += ", be = x"
8612855Sgabeblack@google.com    a += ", sw = %d" % (self.stream_width)
8712855Sgabeblack@google.com    return a
8812855Sgabeblack@google.com
8912855Sgabeblack@google.com
9012855Sgabeblack@google.comdef txn_generator(nr):
9112855Sgabeblack@google.com  pr_read = 0.5
9212855Sgabeblack@google.com  pr_byte_enable = 0.5
9312855Sgabeblack@google.com  pr_enabled = 0.5
9412855Sgabeblack@google.com  bus_widths = [1, 2, 4, 8, 16]
9512855Sgabeblack@google.com  data_widths = [1, 2, 4, 8, 16] + [1, 2, 4, 8] + [1, 2, 4] + [1, 2]
9613709Sandreas.sandberg@arm.com  lengths = list(range(1,33)) + list(range(1,17)) + list(range(1,9)) + list(range(1,5)) + list(range(1,3))
9712855Sgabeblack@google.com  pr_short_be = 0.2
9812855Sgabeblack@google.com  pr_stream = 0.1
9912855Sgabeblack@google.com  nr_generated = 0
10012855Sgabeblack@google.com  while nr_generated < nr:
10112855Sgabeblack@google.com    # create a random transaction
10212855Sgabeblack@google.com    bus_width = random.choice(bus_widths)
10312855Sgabeblack@google.com    while True:
10412855Sgabeblack@google.com      data_width = random.choice(data_widths)
10512855Sgabeblack@google.com      if data_width <= bus_width:  break
10612855Sgabeblack@google.com      if random.random() < 0.25:  break
10712855Sgabeblack@google.com    length = random.choice(lengths)
10813709Sandreas.sandberg@arm.com    addr_base = random.choice(list(range(0,1024,bus_width)))
10913709Sandreas.sandberg@arm.com    addr_offset = random.choice(list(range(bus_width))+[0]*(bus_width/2))
11012855Sgabeblack@google.com    txn = transaction(
11112855Sgabeblack@google.com      bus_width = bus_width,
11212855Sgabeblack@google.com      data_width = data_width,
11312855Sgabeblack@google.com      read_not_write = random.random() < pr_read,
11412855Sgabeblack@google.com      length = length * data_width,
11512855Sgabeblack@google.com      address = addr_base + addr_offset,
11612855Sgabeblack@google.com      byte_enable = False,
11712855Sgabeblack@google.com      stream_width = length * data_width,
11812855Sgabeblack@google.com      data_pointer = random.randint(0,1023)
11912855Sgabeblack@google.com    )
12012855Sgabeblack@google.com    if random.random() < pr_byte_enable:
12112855Sgabeblack@google.com      belen = length
12212855Sgabeblack@google.com      if random.random() < pr_short_be:
12312855Sgabeblack@google.com        belen = min(random.choice(lengths), length)
12412855Sgabeblack@google.com      bep = ["0" * data_width, "1" * data_width]
12512855Sgabeblack@google.com      txn.byte_enable = "".join([random.choice(bep) for x in range(belen)])
12612855Sgabeblack@google.com    if random.random() < pr_stream and length > 1:
12712855Sgabeblack@google.com      strlen = length
12812855Sgabeblack@google.com      while True:
12912855Sgabeblack@google.com        strlen -= 1
13012855Sgabeblack@google.com        if strlen == 1 or \
13112855Sgabeblack@google.com          (random.random() < 0.5 and (length/strlen)*strlen == length):
13212855Sgabeblack@google.com          break
13312855Sgabeblack@google.com      txn.stream_width = strlen * data_width
13412855Sgabeblack@google.com    nr_generated += 1
13512855Sgabeblack@google.com    yield txn
13612855Sgabeblack@google.com
13712855Sgabeblack@google.com# test code for transaction generator
13812855Sgabeblack@google.comif False:
13912855Sgabeblack@google.com  for t in txn_generator(20):
14012855Sgabeblack@google.com    print t
14112855Sgabeblack@google.com  raise Exception
14212855Sgabeblack@google.com# end test code
14312855Sgabeblack@google.com
14412855Sgabeblack@google.com
14512855Sgabeblack@google.comclass memory_state_cl:
14612855Sgabeblack@google.com  buffer_size = 2048
14712855Sgabeblack@google.com  repeats = 10 * buffer_size / 36
14812855Sgabeblack@google.com  population = (string.lowercase + string.digits) * repeats
14912855Sgabeblack@google.com  def __init__(self):
15012855Sgabeblack@google.com    self.initiator = "".join(
15112855Sgabeblack@google.com      random.sample(memory_state_cl.population, memory_state_cl.buffer_size))
15212855Sgabeblack@google.com    self.target =  "".join(
15312855Sgabeblack@google.com      random.sample(memory_state_cl.population, memory_state_cl.buffer_size))
15412855Sgabeblack@google.com  def copy(self):
15512855Sgabeblack@google.com    r = memory_state_cl()
15612855Sgabeblack@google.com    r.initiator = self.initiator
15712855Sgabeblack@google.com    r.target = self.target
15812855Sgabeblack@google.com    return r
15912855Sgabeblack@google.com  def __eq__(self, golden):
16012855Sgabeblack@google.com    return self.initiator==golden.initiator and self.target==golden.target
16112855Sgabeblack@google.com  def __ne__(self, golden):
16212855Sgabeblack@google.com    return self.initiator!=golden.initiator or self.target!=golden.target
16312855Sgabeblack@google.com  def __str__(self):
16412855Sgabeblack@google.com    return "initiator = " + self.initiator + "\n" + "target = " + self.target
16512855Sgabeblack@google.com
16612855Sgabeblack@google.com
16712855Sgabeblack@google.com# all fragmentation generators
16812855Sgabeblack@google.comdef __FRAG__null(txn):
16912855Sgabeblack@google.com  yield txn
17012855Sgabeblack@google.com
17112855Sgabeblack@google.comdef __FRAG__word(txn):
17212855Sgabeblack@google.com  curr_address = txn.address
17312855Sgabeblack@google.com  reset_address = curr_address + txn.stream_width
17412855Sgabeblack@google.com  if txn.byte_enable:
17512855Sgabeblack@google.com    full_byte_enable = txn.byte_enable * (1+txn.length/len(txn.byte_enable))
17612855Sgabeblack@google.com  be_pos = 0
17712855Sgabeblack@google.com  d_pos = txn.data_pointer
17812855Sgabeblack@google.com  end = txn.length + d_pos
17912855Sgabeblack@google.com  while d_pos < end:
18012855Sgabeblack@google.com    new_txn = transaction(
18112855Sgabeblack@google.com      bus_width = txn.bus_width,
18212855Sgabeblack@google.com      data_width = txn.data_width,
18312855Sgabeblack@google.com      read_not_write = txn.read_not_write,
18412855Sgabeblack@google.com      length = txn.data_width,
18512855Sgabeblack@google.com      address = curr_address,
18612855Sgabeblack@google.com      byte_enable = False,
18712855Sgabeblack@google.com      stream_width = txn.data_width,
18812855Sgabeblack@google.com      data_pointer = d_pos
18912855Sgabeblack@google.com    )
19012855Sgabeblack@google.com    curr_address += txn.data_width
19112855Sgabeblack@google.com    if curr_address == reset_address:  curr_address = txn.address
19212855Sgabeblack@google.com    d_pos += txn.data_width
19312855Sgabeblack@google.com    if txn.byte_enable:
19412855Sgabeblack@google.com      new_txn.byte_enable = full_byte_enable[be_pos:be_pos+txn.data_width]
19512855Sgabeblack@google.com      be_pos += txn.data_width
19612855Sgabeblack@google.com    yield new_txn
19712855Sgabeblack@google.com
19812855Sgabeblack@google.comdef __FRAG__stream(txn):
19912855Sgabeblack@google.com  if txn.byte_enable:
20012855Sgabeblack@google.com    full_byte_enable = txn.byte_enable * (1+txn.length/len(txn.byte_enable))
20112855Sgabeblack@google.com  be_pos = 0
20212855Sgabeblack@google.com  bytes_done = 0
20312855Sgabeblack@google.com  while bytes_done < txn.length:
20412855Sgabeblack@google.com    new_txn = transaction(
20512855Sgabeblack@google.com      bus_width = txn.bus_width,
20612855Sgabeblack@google.com      data_width = txn.data_width,
20712855Sgabeblack@google.com      read_not_write = txn.read_not_write,
20812855Sgabeblack@google.com      length = txn.stream_width,
20912855Sgabeblack@google.com      address = txn.address,
21012855Sgabeblack@google.com      byte_enable = False,
21112855Sgabeblack@google.com      stream_width = txn.stream_width,
21212855Sgabeblack@google.com      data_pointer = bytes_done + txn.data_pointer
21312855Sgabeblack@google.com    )
21412855Sgabeblack@google.com    if txn.byte_enable:
21512855Sgabeblack@google.com      new_txn.byte_enable = full_byte_enable[be_pos:be_pos+txn.stream_width]
21612855Sgabeblack@google.com      be_pos += txn.stream_width
21712855Sgabeblack@google.com    yield new_txn
21812855Sgabeblack@google.com    bytes_done += txn.stream_width
21912855Sgabeblack@google.com
22012855Sgabeblack@google.comdef __FRAG__random(stream_txn):
22112855Sgabeblack@google.com  for txn in __FRAG__stream(stream_txn):
22212855Sgabeblack@google.com    # txn has full byte enables and no stream feature guaranteed
22312855Sgabeblack@google.com    pr_nofrag = 0.5
22412855Sgabeblack@google.com    end_address = txn.address + txn.length
22512855Sgabeblack@google.com    curr_address = txn.address
22612855Sgabeblack@google.com    be_pos = 0
22712855Sgabeblack@google.com    d_pos = txn.data_pointer
22812855Sgabeblack@google.com    while curr_address < end_address:
22912855Sgabeblack@google.com      new_txn = transaction(
23012855Sgabeblack@google.com        bus_width = txn.bus_width,
23112855Sgabeblack@google.com        data_width = txn.data_width,
23212855Sgabeblack@google.com        read_not_write = txn.read_not_write,
23312855Sgabeblack@google.com        length = txn.data_width,
23412855Sgabeblack@google.com        address = curr_address,
23512855Sgabeblack@google.com        byte_enable = txn.byte_enable,
23612855Sgabeblack@google.com        stream_width = txn.data_width,
23712855Sgabeblack@google.com        data_pointer = d_pos
23812855Sgabeblack@google.com      )
23912855Sgabeblack@google.com      curr_address += txn.data_width
24012855Sgabeblack@google.com      d_pos += txn.data_width
24112855Sgabeblack@google.com      if txn.byte_enable:
24212855Sgabeblack@google.com        new_txn.byte_enable = txn.byte_enable[be_pos:be_pos+txn.data_width]
24312855Sgabeblack@google.com        be_pos += txn.data_width
24412855Sgabeblack@google.com      while random.random() < pr_nofrag and curr_address < end_address:
24512855Sgabeblack@google.com        new_txn.length += txn.data_width
24612855Sgabeblack@google.com        new_txn.stream_width += txn.data_width
24712855Sgabeblack@google.com        curr_address += txn.data_width
24812855Sgabeblack@google.com        d_pos += txn.data_width
24912855Sgabeblack@google.com        if txn.byte_enable:
25012855Sgabeblack@google.com          new_txn.byte_enable += txn.byte_enable[be_pos:be_pos+txn.data_width]
25112855Sgabeblack@google.com          be_pos += txn.data_width
25212855Sgabeblack@google.com      yield new_txn
25312855Sgabeblack@google.com
25412855Sgabeblack@google.comdef __FRAG__randinterleave(stream_txn):
25512855Sgabeblack@google.com  for txn in __FRAG__stream(stream_txn):
25612855Sgabeblack@google.com    # txn has full byte enables and no stream feature guaranteed
25712855Sgabeblack@google.com    pr_frag = 0.5
25812855Sgabeblack@google.com    txns = [ transaction(
25912855Sgabeblack@google.com      bus_width = txn.bus_width,
26012855Sgabeblack@google.com      data_width = txn.data_width,
26112855Sgabeblack@google.com      read_not_write = txn.read_not_write,
26212855Sgabeblack@google.com      length = txn.length,
26312855Sgabeblack@google.com      address = txn.address,
26412855Sgabeblack@google.com      byte_enable = "",
26512855Sgabeblack@google.com      stream_width = txn.length,
26612855Sgabeblack@google.com      data_pointer = txn.data_pointer
26712855Sgabeblack@google.com    ), transaction(
26812855Sgabeblack@google.com      bus_width = txn.bus_width,
26912855Sgabeblack@google.com      data_width = txn.data_width,
27012855Sgabeblack@google.com      read_not_write = txn.read_not_write,
27112855Sgabeblack@google.com      length = txn.length,
27212855Sgabeblack@google.com      address = txn.address,
27312855Sgabeblack@google.com      byte_enable = "",
27412855Sgabeblack@google.com      stream_width = txn.length,
27512855Sgabeblack@google.com      data_pointer = txn.data_pointer
27612855Sgabeblack@google.com    ) ]
27712855Sgabeblack@google.com    curr = 0
27812855Sgabeblack@google.com    be_pos = 0
27912855Sgabeblack@google.com    on = "1" * txn.data_width
28012855Sgabeblack@google.com    off = "0" * txn.data_width
28112855Sgabeblack@google.com    while be_pos < txn.length:
28212855Sgabeblack@google.com      if txn.byte_enable:  bew = txn.byte_enable[be_pos:be_pos+txn.data_width]
28312855Sgabeblack@google.com      else:  bew = on
28412855Sgabeblack@google.com      txns[curr].byte_enable += bew
28512855Sgabeblack@google.com      txns[1-curr].byte_enable += off
28612855Sgabeblack@google.com      be_pos += txn.data_width
28712855Sgabeblack@google.com      if random.random() < pr_frag:  curr = 1-curr
28812855Sgabeblack@google.com    yield txns[0]
28912855Sgabeblack@google.com    yield txns[1]
29012855Sgabeblack@google.com
29112855Sgabeblack@google.comfragmenters = [globals()[n] for n in globals().keys() if n[:8]=="__FRAG__"]
29212855Sgabeblack@google.com
29312855Sgabeblack@google.com# test code for fragmenters
29412855Sgabeblack@google.comif False:
29512855Sgabeblack@google.com  for t in txn_generator(1):
29612855Sgabeblack@google.com    print t
29712855Sgabeblack@google.com    print
29812855Sgabeblack@google.com    for u in fragmenters[4](t):
29912855Sgabeblack@google.com      print u
30012855Sgabeblack@google.com  raise Exception
30112855Sgabeblack@google.com# end test code
30212855Sgabeblack@google.com
30312855Sgabeblack@google.com
30412855Sgabeblack@google.com# conversion functions are determined by an index (shared with C++) and
30512855Sgabeblack@google.com# a function that tests if they can be applied to a transaction
30612855Sgabeblack@google.comdef __CHCK__generic(txn):
30712855Sgabeblack@google.com  __CHCK__generic.nr = 0
30812855Sgabeblack@google.com  return True
30912855Sgabeblack@google.com
31012855Sgabeblack@google.comdef __CHCK__word(txn):
31112855Sgabeblack@google.com  __CHCK__word.nr = 1
31212855Sgabeblack@google.com  if txn.data_width > txn.bus_width:  return False
31312855Sgabeblack@google.com  if txn.stream_width < txn.length:  return False
31412855Sgabeblack@google.com  if txn.byte_enable and len(txn.byte_enable) < txn.length:  return False
31512855Sgabeblack@google.com  return True
31612855Sgabeblack@google.com
31712855Sgabeblack@google.comdef __CHCK__aligned(txn):
31812855Sgabeblack@google.com  __CHCK__aligned.nr = 2
31912855Sgabeblack@google.com  if txn.data_width > txn.bus_width:  return False
32012855Sgabeblack@google.com  if txn.stream_width < txn.length:  return False
32112855Sgabeblack@google.com  if txn.byte_enable and len(txn.byte_enable) < txn.length:  return False
32212855Sgabeblack@google.com  base_addr = txn.address / txn.bus_width
32312855Sgabeblack@google.com  if base_addr * txn.bus_width != txn.address:  return False
32412855Sgabeblack@google.com  nr_bus_words = txn.length / txn.bus_width
32512855Sgabeblack@google.com  if nr_bus_words * txn.bus_width != txn.length:  return False
32612855Sgabeblack@google.com  return True
32712855Sgabeblack@google.com
32812855Sgabeblack@google.comdef __CHCK__single(txn):
32912855Sgabeblack@google.com  __CHCK__single.nr = 3
33012855Sgabeblack@google.com  if txn.length != txn.data_width:  return False
33112855Sgabeblack@google.com  base_addr = txn.address / txn.bus_width
33212855Sgabeblack@google.com  end_base_addr = (txn.address + txn.length - 1) / txn.bus_width
33312855Sgabeblack@google.com  if base_addr != end_base_addr:  return False
33412855Sgabeblack@google.com  return True
33512855Sgabeblack@google.com
33612855Sgabeblack@google.comdef __CHCK__local_single(txn):
33712855Sgabeblack@google.com  __CHCK__local_single.nr = 4
33812855Sgabeblack@google.com  if txn.length != txn.data_width:  return False
33912855Sgabeblack@google.com  return True
34012855Sgabeblack@google.com
34112855Sgabeblack@google.comall_converters = [globals()[n] for n in globals().keys() if n[:8]=="__CHCK__"]
34212855Sgabeblack@google.comfor x in all_converters:  x.usage = 0
34312855Sgabeblack@google.com
34412855Sgabeblack@google.com
34512855Sgabeblack@google.comclass TesterFailure(Exception):  pass
34612855Sgabeblack@google.comclass SystemCFailure(Exception):  pass
34712855Sgabeblack@google.comclass ConverterDifference(Exception):  pass
34812855Sgabeblack@google.comclass FragmenterDifference(Exception):  pass
34912855Sgabeblack@google.com
35012855Sgabeblack@google.comfrom subprocess import Popen, PIPE
35112855Sgabeblack@google.com
35212855Sgabeblack@google.com# test a single fragment in multiple ways
35312855Sgabeblack@google.comdef test_a_fragment(f, ms):
35412855Sgabeblack@google.com  # f is the (fragment of a) transaction
35512855Sgabeblack@google.com  # ms is the memory state to use at start of test
35612855Sgabeblack@google.com
35712855Sgabeblack@google.com  # run the same fragment through all applicable conversion functions
35812855Sgabeblack@google.com  # and check they all do the same thing
35912855Sgabeblack@google.com  # use the same sub-process for all of them
36012855Sgabeblack@google.com
36112855Sgabeblack@google.com  # build complete stdin
36212855Sgabeblack@google.com  convs = [c for c in all_converters if c(f)]
36312855Sgabeblack@google.com  if len(convs) == 0:  raise TesterFailure(f.str())
36412855Sgabeblack@google.com  txtin = "\n".join(
36512855Sgabeblack@google.com    [("%s\n%s\nconverter = %d\n" % (f, ms, c.nr)) for c in convs])
36612855Sgabeblack@google.com
36712855Sgabeblack@google.com  # run and get stdout
36812855Sgabeblack@google.com  txtout = "no output"
36912855Sgabeblack@google.com  try:
37012855Sgabeblack@google.com    sp = Popen("../build-unix/test_endian_conv.exe", stdin=PIPE, stdout=PIPE)
37112855Sgabeblack@google.com    txtout = sp.communicate(txtin)[0]
37212855Sgabeblack@google.com    tmp = txtout.splitlines()
37312855Sgabeblack@google.com    initiators = [l.split()[-1] for l in tmp if l[:14] == "  initiator = "]
37412855Sgabeblack@google.com    targets = [l.split()[-1] for l in tmp if l[:11] == "  target = "]
37512855Sgabeblack@google.com  except:
37612855Sgabeblack@google.com    raise SystemCFailure("\n" + txtin + txtout)
37712855Sgabeblack@google.com  if sp.returncode != 0:  raise SystemCFailure("\n" + txtin + txtout)
37812855Sgabeblack@google.com  if len(initiators) != len(convs):  raise SystemCFailure("\n" + txtin + txtout)
37912855Sgabeblack@google.com  if len(targets) != len(convs):  raise SystemCFailure("\n" + txtin + txtout)
38012855Sgabeblack@google.com  for c in convs:  c.usage += 1
38112855Sgabeblack@google.com
38212855Sgabeblack@google.com  ms_out = memory_state_cl()
38312855Sgabeblack@google.com  ms_out.initiator = initiators[0]
38412855Sgabeblack@google.com  ms_out.target = targets[0]
38512855Sgabeblack@google.com  for i in range(1,len(convs)):
38612855Sgabeblack@google.com    if initiators[i]!=ms_out.initiator or targets[i]!=ms_out.target:
38712855Sgabeblack@google.com      raise ConverterDifference("""
38812855Sgabeblack@google.com%s
38912855Sgabeblack@google.comstart memory:
39012855Sgabeblack@google.com%s
39112855Sgabeblack@google.comconverter = %d
39212855Sgabeblack@google.comgolden memory:
39312855Sgabeblack@google.com%s
39412855Sgabeblack@google.comactual memory:
39512855Sgabeblack@google.com%s""" % (f, ms, i, golden_ms, ms_out))
39612855Sgabeblack@google.com
39712855Sgabeblack@google.com  return ms_out
39812855Sgabeblack@google.com
39912855Sgabeblack@google.com
40012855Sgabeblack@google.com# main loop
40112855Sgabeblack@google.com
40212855Sgabeblack@google.comfrom sys import argv
40312855Sgabeblack@google.com
40412855Sgabeblack@google.comprint "Testing Endianness Conversion Functions"
40512855Sgabeblack@google.comprint "March 2008"
40612855Sgabeblack@google.comprint "OSCI TLM-2"
40712855Sgabeblack@google.com
40812855Sgabeblack@google.comtry:  nr_txns_to_test = int(argv[1])
40912855Sgabeblack@google.comexcept:
41012855Sgabeblack@google.com  print "No command line input for number of tests, using default"
41112855Sgabeblack@google.com  nr_txns_to_test = 1000
41212855Sgabeblack@google.com
41312855Sgabeblack@google.comprint "Number to test:", nr_txns_to_test
41412855Sgabeblack@google.com
41512855Sgabeblack@google.com# generate and test a number of transactions
41612855Sgabeblack@google.comfor txn in txn_generator(nr_txns_to_test):
41712855Sgabeblack@google.com
41812855Sgabeblack@google.com  # each transaction has a random initial memory state
41912855Sgabeblack@google.com  initial_memory = memory_state_cl()
42012855Sgabeblack@google.com
42112855Sgabeblack@google.com  # iterate over all defined fragmentation functions
42212855Sgabeblack@google.com  first_time = True
42312855Sgabeblack@google.com  for fragmenter in fragmenters:
42412855Sgabeblack@google.com
42512855Sgabeblack@google.com    # all versions of the transaction start in the same place
42612855Sgabeblack@google.com    memory_state = initial_memory.copy()
42712855Sgabeblack@google.com
42812855Sgabeblack@google.com    # now iterate over the fragments of the transaction, accumulating
42912855Sgabeblack@google.com    # the memory state
43012855Sgabeblack@google.com    for partial_txn in fragmenter(txn):
43112855Sgabeblack@google.com      memory_state = test_a_fragment(partial_txn, memory_state)
43212855Sgabeblack@google.com
43312855Sgabeblack@google.com    if first_time:
43412855Sgabeblack@google.com      golden_memory_state = memory_state.copy()
43512855Sgabeblack@google.com      first_time = False
43612855Sgabeblack@google.com    else:
43712855Sgabeblack@google.com      if memory_state != golden_memory_state:  raise FragmenterDifference("""
43812855Sgabeblack@google.comfragmenter: %s
43912855Sgabeblack@google.comtransaction:
44012855Sgabeblack@google.com%s
44112855Sgabeblack@google.comstart memory:
44212855Sgabeblack@google.com%s
44312855Sgabeblack@google.comgolden memory:
44412855Sgabeblack@google.com%s
44512855Sgabeblack@google.comactual memory:
44612855Sgabeblack@google.com%s""" % (fragmenter, txn, initial_memory, golden_memory_state, memory_state))
44712855Sgabeblack@google.com
44812855Sgabeblack@google.com  print ".",
44912855Sgabeblack@google.comprint
45012855Sgabeblack@google.com
45112855Sgabeblack@google.com
45212855Sgabeblack@google.comprint "Conversion functions usage frequency:"
45312855Sgabeblack@google.comfor c in all_converters:
45412855Sgabeblack@google.com  print c.nr, c.__name__, c.usage
45512855Sgabeblack@google.com
45612855Sgabeblack@google.com
457