#! /usr/bin/env python3 # vim: set fileencoding=utf-8 # Copyright (c) 2018, Technische Universität Kaiserslautern # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # # 1. Redistributions of source code must retain the above copyright notice, # this list of conditions and the following disclaimer. # # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # 3. Neither the name of the copyright holder nor the names of its # contributors may be used to endorse or promote products derived from # this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER # OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF # LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # # Author: Éder F. Zulian import ctypes # A trace file is a pre-recorded file containing memory transactions. Each # memory transaction has a timestamp that tells the simulator when it shall # happen, a transaction type (read or write) and a memory address given in # hexadecimal. # # Here is an example syntax: # # ``` # # Comment lines begin with # # # [clock-cyle]: [write|read] [hex-address] # 31: read 0x400140 # 33: read 0x400160 # 56: write 0x7fff8000 # 81: read 0x400180 # ``` # # The timestamp corresponds to the time the request is to be issued and it is # given in cycles of the bus master device. Example: the device is a FPGA with # frequency 200 MHz (clock period of 5 ns). If the timestamp is 10 it means # that the request is to be issued when time is 50 ns. # # The default values given as example assume the following address mapping: # # DIMM Characteristics: # Byte Offset (Y): 8 [0:2] (8-byte-wide memory module, i.e., 64-bit-wide data bus) -> 3 bit # Cols (C): 1K [3:12] (A0 - A9) -> 10 bit # Rows (R): 128K [13:29] (A0 - A16) -> 17 bit # Bank (B): 8 [30:32] (BA0 - BA2) -> 3 bit # # 3 3 3 | 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 | 1 1 1 # 2 1 0 | 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 | 2 1 0 9 8 7 6 5 4 3 | 2 1 0 # B B B | R R R R R R R R R R R R R R R R R | C C C C C C C C C C | Y Y Y # # Transaction type (read or write) transaction = 'read' # Channel information. If your address mapping does not have channel bits keep # it equal to 1 and set the shift to the extreme left of the address. num_ch = 1 # Number of channels ch_shift = 34 # Shift to reach the frist bit reserved for channels in the address ch_mask = 0x1 # Mask for all channel bits in the address # Bank group information. If your address mapping does not have bank groups # keep it equal to 1 and set the shift to the extreme left of the address. num_bank_groups = 1 # Number of bank groups bgroup_shift = 33 # Shift to reach the frist bit reserved for bank groups in the address bgroup_mask = 0x1 # Mask for all bits in the address related to bank groups # Bank information num_banks = 8 # Number of banks bank_shift = 30 # Shift to reach the frist bit reserved for banks in the address bank_mask = 0x7 # Mask for all bank bits in the address # Row information num_rows = 128 * 1024 # Number of rows row_shift = 13 # Shift to reach the frist bit reserved for rows in the address row_mask = 0x1ffff # Mask for all row bits in the address # Column information num_col = 1 * 1024 # Number of columns col_shift = 3 # Shift to reach the frist bit reserved for columns in the address col_mask = 0x3ff # Mask for all column bits in the address # Burst length of 8 columns. 8 columns written/read per access (in 4 full # clock cycles of the memory bus). burst_len = 8 # Initial clock cycle clock_cycle = 0 # Clock cycle increment between two accesses clock_increment = 10 def clear_bits(mask, shift, val): m = ctypes.c_uint64(~(mask << shift)).value return ctypes.c_uint64(val & m).value def set_bits(mask, shift, val, v): val = clear_bits(mask, shift, val) return ctypes.c_uint64(val | (v << shift)).value address = 0 for ch in range(0, num_ch): address = set_bits(ch_mask, ch_shift, address, ch) for bg in range(0, num_bank_groups): address = set_bits(bgroup_mask, bgroup_shift, address, bg) for b in range(0, num_banks): address = set_bits(bank_mask, bank_shift, address, b) for row in range(0, num_rows): address = set_bits(row_mask, row_shift, address, row) for col in range(0, num_col, burst_len): address = set_bits(col_mask, col_shift, address, col) print('# clock cycle: {0:d} | {1} | address: 0x{2:010X} | channel: {3} | bank group: {4} | bank: {5} | row: {6} | column: {7}'.format(clock_cycle, transaction, address, ch, bg, b, row, col)) print('{0:d}:\t{1}\t0x{2:010X}'.format(clock_cycle, transaction, address)) clock_cycle = clock_cycle + clock_increment