wrc_main_sim.c 6.7 KB
Newer Older
1
/* ****************************************************************************
2 3
 * This work is part of the White Rabbit project
 *
4
 * Copyright (C) 2017 CERN (www.cern.ch)
5
 * Author: Grzegorz Daniluk <grzegorz.daniluk@cern.ch>
6
 * Author: Maciej Lipinski <maciej.lipinski@cern.ch>
7
 * Author: Adam Wujek <adam.wujek@cern.ch>
8 9
 *
 * Released according to the GNU GPL, version 2 or any later version.
10 11 12 13
 *
 * ****************************************************************************
 * Description:
 * This file provides the main() function that replaces the main function of
14
 * wrc_main.c file when WRPC is compiled for testbench. This is done by
15
 * configuring WRPC using make menuconfig:
16
 * a) by using the default wrpc_sim_defconfig, i.e. "make wrpc_sim_defconfig",or
17 18 19 20 21 22 23
 * b) by chosing in make menuconfig the following opton:
 *    "Build simple software for test of WR PTP Core in simulatin"
 *
 * When compiled for testbench simulation, the main() function of this file is
 * used. This file includes all the tests needed for different testbenches
 * (so far only one...)
 * ****************************************************************************
24
 */
25

26 27 28 29
#include <stdio.h>
#include <inttypes.h>

#include "system_checks.h"
30 31 32 33 34 35
#include "endpoint.h"
#include "minic.h"
#include "pps_gen.h"
#include "softpll_ng.h"
#include <wrpc.h> /*needed for htons()*/

36 37
#define TESTBENCH_MAGIC 0x4d433ebc
#define TESTBENCH_VERSION 1
38
#define TESTBENCH_RET_NO_TEST 0
39 40
#define TESTBENCH_RET_OK 1
#define TESTBENCH_RET_ERROR 2
41

42

43
/*
44 45
 * This is a structure to pass information from the testbench to lm32's
 * software. hdl_testbench structure is meant to be set by testbench through
46
 * memory-manipulation.
47
 *
48 49 50
 * At the address HDL_TESTBENCH_PADDR is a pointer to hdl_testbench structure.
 * hdl_testbench_t structure can be expanded to carry information with any
 * size.
51
 *
52
 * The idea behind is that different tests for different testbenches are
53 54 55
 * compiled in this file, and the proper test is loaded based on variable 
 * hdl_testbench.test_num.
 * Each HDL testbench sets the proper testbench number at the startup.
56
 */
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71

struct hdl_testbench_t {
	uint32_t magic;
	uint32_t version;
	uint32_t test_num;
	uint32_t return_val;
};

struct hdl_testbench_t hdl_testbench = {
	.magic = TESTBENCH_MAGIC,
	.version = TESTBENCH_VERSION,
	.test_num = 0,
};

int wrpc_test_1(void);
72

73 74 75
/*
 * Basic initialization required for simulation
 */
76 77
static void wrc_sim_initialize(void)
{
78
	uint8_t mac_addr[6];
79

80 81 82 83 84 85 86
	// Search SDB for devices takes too long, hard-coded offsets
	// should work for most WR-PTP core implementations
	// (unless you add/remove/move peripherals), in which case
	// you should comment out all the hard-coded offsets and
	// uncomment the following line to perform a dynamic search
	// at runtime.
	//sdb_find_devices();
87 88 89 90 91 92 93 94
	BASE_MINIC         = (void *)0x20000;
	BASE_EP            = (void *)0x20100;
	BASE_SOFTPLL       = (void *)0x20200;
	BASE_PPS_GEN       = (void *)0x20300;
	BASE_SYSCON        = (void *)0x20400;
	BASE_UART          = (void *)0x20500;
	BASE_ONEWIRE       = (void *)0x20600;
	BASE_ETHERBONE_CFG = (void *)0x20700;
95

96
	timer_init(1);
97

98 99 100 101 102 103 104
	/* Source MAC used by WRPC's Endpoint */
	mac_addr[0] = 0xDE;
	mac_addr[1] = 0xAD;
	mac_addr[2] = 0xBE;
	mac_addr[3] = 0xEF;
	mac_addr[4] = 0xBA;
	mac_addr[5] = 0xBE;
105

106 107
	ep_init(mac_addr);
	ep_enable(1, 1);
108

109 110 111
	minic_init();
	shw_pps_gen_init();
	spll_very_init();
112 113
  /* wait for link up before enabling tm_time_valid_o */
  while (ep_link_up(NULL) == 0) {}
114
	shw_pps_gen_enable_output(1);
115 116
}
/*
117
 * This is a test used by:
118 119
 * - WRPC testbench located in "testbench/wrc_core" folder of the wr-cores
 *   repository (git://ohwr.org/hdl-core-lib/wr-cores.git)
120 121
 *
 * This test:
122 123 124 125 126 127 128
 * - sends min-size frames of PTP EtherType (0x88f7) and Dst MAC
 *   (01:1B:19:00:00:00) with embedded sequence number and flags providing
 *   information about the previously received frame
 * - checkes whether the transmitted frames are successfully received back in a
 *   proper sequence (it is supposed that the testbench loops back the frames)
 * - embeds in the next frame flag and return value regarding the previously
 *   received frames, i.e.:
129 130 131 132 133
 *   # the flags say:
 *     0xAA: this is the first frame (no previous frames)
 *     0xBB: previous frame was successfully received
 *     0xE*: something was wrong with the previously received frame
 *   # return value - it is the value returned by the reception funcation
134 135 136
 *
 */
int wrpc_test_1(void)
137
{
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
	struct hw_timestamp hwts;
	struct wr_ethhdr_vlan tx_hdr;
	struct wr_ethhdr rx_hdr;
	int j;
	uint8_t tx_payload[NET_MAX_SKBUF_SIZE - 32];
	uint8_t rx_payload[NET_MAX_SKBUF_SIZE - 32];
	int ret = 0;
	int tx_cnt = 0, rx_cnt = 0, pl_cnt;
	/* error code:
	 * 0xAA - first
	 * 0xBB - normal
	 * 0xE* - error code:
	 *    0 - Error: returned zero value
	 *    1 - Error: wrong seqID
	 *    2 - Error: error of rx */
	int code = 0xAA;

	/** prepare dummy frame */
	/* payload */
	for (j = 0; j < 80; ++j)
		tx_payload[j] = 0xC7;/* j; */

	/* MAC address and EtherType of PTP */
	memcpy(tx_hdr.dstmac, "\x01\x1B\x19\x00\x00\x00", 6);
	tx_hdr.ethtype = htons(0x88f7);

164
	hdl_testbench.return_val = TESTBENCH_RET_OK;
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
	/** main loop, send test frames */
	for (;;) {
		/* seqID */
		tx_payload[0] = 0xFF & (tx_cnt >> 8);
		tx_payload[1] = 0xFF & tx_cnt;

		tx_payload[2] = 0xFF & (code >> 8);
		tx_payload[3] = 0xFF & code;

		/* rx return value */
		tx_payload[4] = 0xFF & (ret >> 8);
		tx_payload[5] = 0xFF & ret;

		/* A frame is sent out with sequenceID (firt octet) and awaited
		 * reception. */
		minic_tx_frame(&tx_hdr, tx_payload, 62, &hwts);
		tx_cnt++;
		ret = minic_rx_frame(&rx_hdr, rx_payload, NET_MAX_SKBUF_SIZE,
				&hwts);

		/** check whether the received value is OK */
186
		if (ret == 0) {
187
			code = 0xE0; /* Error: returned zero value */
188 189
			hdl_testbench.return_val = TESTBENCH_RET_ERROR;
		}
190
		else if (ret > 0) {
191
			pl_cnt = 0xFFFF & ((tx_payload[0] << 8) | tx_payload[1]);
192 193 194
			if (pl_cnt == rx_cnt) {
				rx_cnt++;
				code = 0xBB; /* OK */
195
				hdl_testbench.return_val = TESTBENCH_RET_OK;
196 197 198
			} else {
				rx_cnt = pl_cnt+1;
				code = 0xE1; /* Error: wrong seqID */
199
				hdl_testbench.return_val = TESTBENCH_RET_ERROR;
200
			}
201
		} else {
202
			code = 0xE2; /* Error: error of rx */
203 204
			hdl_testbench.return_val = TESTBENCH_RET_ERROR;
		}
205
	}
206 207

}
208 209

void main(void)
210
{
211 212
	wrc_sim_initialize();

213 214 215 216 217 218 219 220
	if (hdl_testbench.magic != TESTBENCH_MAGIC
	    || hdl_testbench.magic != TESTBENCH_VERSION) {
		/* Wrong testbench structure */
		hdl_testbench.return_val = TESTBENCH_RET_ERROR;
		while (1)
			;
	}
	switch (hdl_testbench.test_num) {
221 222 223 224 225
	case 0:
		/* for simulations that just need link-up */
		hdl_testbench.return_val = TESTBENCH_RET_NO_TEST;
		while (1)
			;
226
	case 1:
227 228 229
		wrpc_test_1();
		break;
	default:
230 231
		/* Wrong test number */
		hdl_testbench.return_val = TESTBENCH_RET_ERROR;
232 233 234
		while (1)
			;
	}
235
}