link: improve and clean up crc_tb, scrambler_tb
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 2 Dec 2014 18:24:46 +0000 (19:24 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Tue, 2 Dec 2014 18:24:46 +0000 (19:24 +0100)
lib/sata/link/crc.py
lib/sata/link/test/Makefile
lib/sata/link/test/common.py
lib/sata/link/test/crc.c
lib/sata/link/test/crc_tb.py
lib/sata/link/test/scrambler.c
lib/sata/link/test/scrambler_tb.py
lib/sata/std.py

index 2f3aa367a74a95dff0b9dee7561f9b84011398ad..e7bb3bb0e6bb1efb1ea9c13bdb143cc19f54c8ca 100644 (file)
@@ -90,7 +90,7 @@ class SATACRC(Module):
        polynom = 0x04C11DB7
        init = 0x52325032
        check = 0xC704DD7B
-       def __init__(self, dat_width):
+       def __init__(self):
                self.d = Signal(self.width)
                self.value = Signal(self.width)
                self.error = Signal()
index 4f621c37b173925fabfe7f753d1f6629cfd2b218..e516221c2a51704c4952637690ad9e7fb83a205a 100644 (file)
@@ -20,4 +20,4 @@ link_tb:
 all: crc_tb scrambler_tb
 
 clean:
-       rm crc scrambler
+       rm crc scrambler *.vcd
index d95c8352adee3f188b203c934f57f900e9c4590b..c5994f020e2ba8866eb17c4bc283010e76e45239 100644 (file)
@@ -1,11 +1,20 @@
+def seed_to_data(seed, random=True):
+       if random:
+               return (seed * 0x31415979 + 1) & 0xffffffff
+       else:
+               return seed
+
 def check(ref, res):
-       shift = 0
-       while((ref[0] != res[0]) and (len(res)>1)):
-               res.pop(0)
-               shift += 1
-       length = min(len(ref), len(res))
-       errors = 0
-       for i in range(length):
-               if ref.pop(0) != res.pop(0):
-                       errors += 1
-       return shift, length, errors
+       if isinstance(ref, int):
+               return 0, 1, int(ref != res)
+       else:
+               shift = 0
+               while((ref[0] != res[0]) and (len(res)>1)):
+                       res.pop(0)
+                       shift += 1
+               length = min(len(ref), len(res))
+               errors = 0
+               for i in range(length):
+                       if ref.pop(0) != res.pop(0):
+                               errors += 1
+               return shift, length, errors
index f4f15954d95cfcda8f86999550503f976afdc2f6..75576b5c1dad8303cd4261c3fa00225e36717b02 100644 (file)
@@ -1,4 +1,35 @@
 // Adapted from SATA specification
+/****************************************************************************/
+/*                                                                          */
+/* crc.c                                                                    */
+/*                                                                          */
+/* This sample code reads standard in for a sequence of 32 bit values       */
+/* formatted in hexadecimal with a leading "0x" (e.g. 0xDEADBEEF). The      */
+/* code calculates the Serial ATA CRC for the input data stream. The        */
+/* generator polynomial used is:                                            */
+/* 32 26 23 22 16 12 11 10 8 7 5 4 2                                        */
+/* G(x) = x + x + x + x + x + x + x + x + x + x + x + x + x + x + 1         */
+/*                                                                          */
+/* This sample code uses a parallel implementation of the CRC calculation   */
+/* circuit that is suitable for implementation in hardware. A block         */
+/* diagram of the circuit being emulated is shown below.                    */
+/*                                                                          */
+/*                   +---+          +---+          +---+                    */
+/* Data_In --------->|   |          |   |          | R |                    */
+/*                   | + |--------->| * |--------->| e |----+               */
+/*             +---->|   |          |   |          | g |    |               */
+/*             |     +---+          +---+          +---+    |               */
+/*             |                                            |               */
+/*             |                                            |               */
+/*             +--------------------------------------------+               */
+/*                                                                          */
+/* The CRC value is initialized to 0x52325032 as defined in the Serial ATA  */
+/* specification.                                                           */
+/*                                                                          */
+/****************************************************************************/
+
+
+
 #include <stdlib.h>
 #include <stdio.h>
 int main(int argc, char *argv[])
@@ -10,19 +41,23 @@ int main(int argc, char *argv[])
    unsigned char crc_bit[32];
    unsigned char new_bit[32];
 
-   data_in = 0x12345678;
    crc = 0x52325032;
    data_count = 0;
 
-   while (data_count < 65536)  {
+   while((scanf(" 0x%8x", &data_in) == 1) && (!scanf("exit"))) {
       data_count++;
-
+      /* Add the data_in value to the current value of the CRC held in the  */
+      /* "register". The addition is performed modulo two (XOR).            */
       crc ^= data_in;
-
+      /* Expand the value of the CRC held in the register to 32 individual  */
+      /* bits for easy manipulation. */
       for (i = 0; i < 32; ++i)  {
          crc_bit[i] = (crc >> i) & 0x01;
       }
-
+      /* The following 32 assignments perform the function of the box       */
+      /* labeled "*" in the block diagram above. The new_bit array is a     */
+      /* temporary holding place for the new CRC value being calculated.    */
+      /* Note that there are lots of shared terms in the assignments below. */
       new_bit[31] = crc_bit[31] ^ crc_bit[30] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[27] ^ crc_bit[25] ^ crc_bit[24] ^
                     crc_bit[23] ^ crc_bit[15] ^ crc_bit[11] ^ crc_bit[9]  ^ crc_bit[8]  ^ crc_bit[5];
       new_bit[30] = crc_bit[30] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[27] ^ crc_bit[26] ^ crc_bit[24] ^ crc_bit[23] ^
@@ -100,13 +135,15 @@ int main(int argc, char *argv[])
       new_bit[0]  = crc_bit[31] ^ crc_bit[30] ^ crc_bit[29] ^ crc_bit[28] ^ crc_bit[26] ^ crc_bit[25] ^ crc_bit[24] ^
                     crc_bit[16] ^ crc_bit[12] ^ crc_bit[10] ^ crc_bit[9]  ^ crc_bit[6]  ^ crc_bit[0];
 
+      /* The new CRC value has been calculated as individual bits in the */
+      /* new_bit array. Re-assembled it into a 32 bit value and "clock" it */
+      /* into the "register". */
       crc = 0;
       for (i = 31; i >= 0; --i)  {
          crc = crc << 1;
          crc |= new_bit[i];
       }
-      printf("%08x\n", crc);
    }
-
+   printf("%08x\n", crc);
    return 0;
 }
index 6639a1939865d4862e1331a2bf764278cf2f494d..0411fd04e261ddb78e01845974bcdd6261ac63ce 100644 (file)
@@ -4,38 +4,57 @@ from migen.fhdl.std import *
 
 from lib.sata.std import *
 from lib.sata.link.crc import *
-from lib.sata.link.test.common import check
+from lib.sata.link.test.common import *
 
 class TB(Module):
-       def __init__(self, length):
+       def __init__(self, length, random):
                self.submodules.crc = SATACRC()
                self.length = length
+               self.random = random
+
+       def get_c_crc(self, datas):
+               stdin = ""
+               for data in datas:
+                       stdin += "0x%08x " %data
+               stdin += "exit"
+               with subprocess.Popen("./crc", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
+                       process.stdin.write(stdin.encode("UTF-8"))
+                       out, err = process.communicate()
+               return int(out.decode("UTF-8"), 16)
 
        def gen_simulation(self, selfp):
-       # init CRC
-               selfp.crc.d = 0x12345678
+               # init CRC
+               selfp.crc.d = 0
                selfp.crc.ce = 1
                selfp.crc.reset = 1
                yield
                selfp.crc.reset = 0
 
-       # get C code results
-               p = subprocess.Popen(["./crc"], stdout=subprocess.PIPE)
-               out, err = p.communicate()
-               ref = [int(e, 16) for e in out.decode("utf-8").split("\n")[:-1]]
+               # feed CRC with datas
+               datas = []
+               for i in range(self.length):
+                       data = seed_to_data(i, self.random)
+                       datas.append(data)
+                       selfp.crc.d = data
+                       yield
 
+               # log results
+               yield
+               sim_crc = selfp.crc.value
 
-       # log results
-               res = []
-               for i in range(self.length):
-                       res.append(selfp.crc.value)
+               # stop
+               selfp.crc.ce = 0
+               for i in range(32):
                        yield
 
-       # check results
-               s, l, e = check(ref, res)
+               # get C core reference
+               c_crc = self.get_c_crc(datas)
+
+               # check results
+               s, l, e = check(c_crc, sim_crc)
                print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
 
 if __name__ == "__main__":
        from migen.sim.generic import run_simulation
        length = 8192
-       run_simulation(TB(length), ncycles=length+100, vcd_name="my.vcd", keep_files=True)
+       run_simulation(TB(length, True), ncycles=length+100, vcd_name="my.vcd")
index d8b0d83034ed4a790e6a1bcc47960b517e1ef9bb..cee4b30a98431a43ce1917fac4a9d5833149d4ec 100644 (file)
 int main(int argc, char *argv[])
 {
    int               i, j;
+   unsigned int      length;
    unsigned short    context;
    unsigned long     scrambler;
    unsigned char     now[16];
    unsigned char     next[32];
    context = 0xF0F6;
 
-   for (i = 0; i < 65536; ++i)  {
+   scanf("0x%8x", &length);
+
+   for (i = 0; i < length; ++i)  {
       for (j = 0; j < 16; ++j)  {
          now[j] = (context >> j) & 0x01;
       }
index 8228ef563537e597e9501d12d15a7f14899bbcc9..86a569ba2abc5300dcdd8f70beb544d01b5894d1 100644 (file)
@@ -4,37 +4,47 @@ from migen.fhdl.std import *
 
 from lib.sata.std import *
 from lib.sata.link.scrambler import *
-from lib.sata.link.test.common import check
+from lib.sata.link.test.common import *
 
 class TB(Module):
        def __init__(self, length):
                self.submodules.scrambler = Scrambler()
                self.length = length
 
+       def get_c_values(self, length):
+               stdin = "0x%08x" %length
+               with subprocess.Popen("./scrambler", stdin=subprocess.PIPE, stdout=subprocess.PIPE) as process:
+                       process.stdin.write(stdin.encode("UTF-8"))
+                       out, err = process.communicate()
+               return [int(e, 16) for e in out.decode("utf-8").split("\n")[:-1]]
+
        def gen_simulation(self, selfp):
-       # init CRC
+               # init CRC
                selfp.scrambler.ce = 1
                selfp.scrambler.reset = 1
                yield
                selfp.scrambler.reset = 0
 
-       # get C code results
-               p = subprocess.Popen(["./scrambler"], stdout=subprocess.PIPE)
-               out, err = p.communicate()
-               ref = [int(e, 16) for e in out.decode("utf-8").split("\n")[:-1]]
-
-       # log results
+               # log results
                yield
-               res = []
+               sim_values = []
                for i in range(self.length):
-                       res.append(selfp.scrambler.value)
+                       sim_values.append(selfp.scrambler.value)
                        yield
 
-       # check results
-               s, l, e = check(ref, res)
+               # stop
+               selfp.scrambler.ce = 0
+               for i in range(32):
+                       yield
+
+               # get C code reference
+               c_values = self.get_c_values(self.length)
+
+               # check results
+               s, l, e = check(c_values, sim_values)
                print("shift "+ str(s) + " / length " + str(l) + " / errors " + str(e))
 
 if __name__ == "__main__":
        from migen.sim.generic import run_simulation
        length = 8192
-       run_simulation(TB(length), ncycles=length+100, vcd_name="my.vcd", keep_files=True)
+       run_simulation(TB(length), ncycles=length+100, vcd_name="my.vcd")
index 191778fc111c373dc839cb135c03e82a41c3b44c..e0f100ea7be49376de1b816a4e6f3cf5d17c3e58 100644 (file)
@@ -22,21 +22,15 @@ def ones(width):
        return 2**width-1
 
 def phy_layout(dw):
-       parameters = {
-               "packetized": False
-       }
        layout = [
                ("data", dw),
                ("charisk", dw//8),
        ]
-       return EndpointDescription(layout, parameters)
+       return EndpointDescription(layout, packetized=False)
 
 def link_layout(dw):
-       parameters = {
-               "packetized": True
-       }
        layout = [
                ("d", dw),
                ("error", 1)
        ]
-       return EndpointDescription(layout, parameters)
+       return EndpointDescription(layout, packetized=True)