⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pci.c

📁 此代码用于生成测试PCI设备的Verilog代码(Verilog代码为一种硬件描述语言)。此代码可以直接运行于LINUX下。
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 2002 Picture Elements, Inc. *    Stephen Williams (steve@picturel.com) * *    This source code is free software; you can redistribute it *    and/or modify it in source code form under the terms of the GNU *    General Public License as published by the Free Software *    Foundation; either version 2 of the License, or (at your option) *    any later version. * *    This program is distributed in the hope that it will be useful, *    but WITHOUT ANY WARRANTY; without even the implied warranty of *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *    GNU General Public License for more details. * *    You should have received a copy of the GNU General Public License *    along with this program; if not, write to the Free Software *    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */#ident "$Id: pci.c,v 1.8 2003/11/07 00:52:26 steve Exp $"/* * $pci_master_command(cmd, op) *   This system task is a hook that the pci_master uses to get the *   next command from the remote. The cmd is a variable that receives *   the opcode, and op is a memory that receives operands. The remote *   sends these values as a list of numbers on a single text line. * * $pci_master_response(code, ...) *   This command is used to send a single response to the remote. * * integer $pci_memory_open("path", <size>); *   This function opens a file referenced by the path, and maps it *   with the given size. It returns a descripter value that can be *   used to reference the file later. * * reg[31:0] $pci_memory_peek(<fd>, <addr>, <bar>); *   This function reads a little-endian value from the mapped file *   that was opened and mapped already. * * $pci_memory_poke(<fd>, <addr>, <value>, <bar>); */# include  <vpi_user.h># include  <stdio.h># include  <stdlib.h># include  <string.h># include  <sys/types.h># include  <sys/stat.h># include  <sys/mman.h># include  <unistd.h># include  <fcntl.h># include  <errno.h># include  <assert.h>static FILE* cfd0 = 0;static FILE* cfd1 = 0;const char*pci_fifo0 = "pci_fifo0";const char*pci_fifo1 = "pci_fifo1";# define CMD_FILL    0x0000# define CMD_COMPARE 0x0001# define CMD_LOAD    0x0002# define CMD_SAVE    0x0003# define CONTROL_COUNT (4096/4)static struct memory_map_t {      int fd;      char*path;      unsigned char*base;      size_t size;      unsigned control_regs[CONTROL_COUNT];} memory_map[1] = {      { -1, 0, 0 }};static void cmd_fill(int id){      unsigned base = memory_map[id].control_regs[1];      unsigned size = memory_map[id].control_regs[2];      unsigned fill = memory_map[id].control_regs[3];      unsigned char fill0 = (fill >>  0) & 0xff;      unsigned char fill1 = (fill >>  8) & 0xff;      unsigned char fill2 = (fill >> 16) & 0xff;      unsigned char fill3 = (fill >> 24) & 0xff;      unsigned idx;      unsigned char* ptr;      if (base >= memory_map[id].size)	    return;      if (size == 0)	    return;      vpi_printf("MEM%d: fill 0x%x - 0x%x with 0x%x\n",		 id, base, base+size*4-1, fill);      if ((base + size*4) > memory_map[id].size)	    size = (memory_map[id].size - base) / 4;      ptr = memory_map[id].base + base;      for (idx = 0 ;  idx < size ;  idx += 1) {	    *ptr++ = fill0;	    *ptr++ = fill1;	    *ptr++ = fill2;	    *ptr++ = fill3;      }}static void cmd_compare(int id){      unsigned base1 = memory_map[id].control_regs[1];      unsigned size1 = memory_map[id].control_regs[2];      unsigned base2 = memory_map[id].control_regs[3];      unsigned idx, rc = 0;      const unsigned char*ba, *bb;      unsigned message_limit = 20;      if (base1 >= memory_map[id].size)	    return;      if (base2 >= memory_map[id].size)	    return;      if (size1 == 0)	    return;      if ((base1 + size1) > memory_map[id].size)	    size1 = memory_map[id].size - base1;      memory_map[id].control_regs[0] = memcmp(memory_map[id].base+base1,					      memory_map[id].base+base2,					      size1);      ba = memory_map[id].base+base1;      bb = memory_map[id].base+base2;      for (idx = 0 ;  idx < size1 ;  idx += 1) {	    if (ba[idx] != bb[idx]) {		  switch (message_limit) {		      case 0:			break;		      case 1:			vpi_printf("MEM%d: More differences...\n", id);			message_limit = 0;			break;		      default:			vpi_printf("MEM%d: %02x at 0x%x != %02x at 0x%x\n",				   id, ba[idx], base1+idx, bb[idx], base2+idx);			message_limit -= 1;			break;		  }		  rc += 1;	    }      }      memory_map[id].control_regs[0] = rc;      vpi_printf("MEM%d: compare 0x%x-0x%x and 0x%x-0x%x returns %x\n", id,		 base1, base1+size1-1, base2, base2+size1-1,		 memory_map[id].control_regs[0]);}static void extract_path_from_load(char*path, int id){      int idx;      for (idx = 0 ;  idx < (CONTROL_COUNT-3) ;  idx += 1) {	    char byte;	    char*dp = path + 4*idx;	    unsigned word = memory_map[id].control_regs[3+idx];	    *dp++ = (byte = (word & 0xff));	    if (byte == 0) break;	    word >>= 8;	    *dp++ = (byte = (word & 0xff));	    if (byte == 0) break;	    word >>= 8;	    *dp++ = (byte = (word & 0xff));	    if (byte == 0) break;	    word >>= 8;	    *dp++ = (byte = (word & 0xff));	    if (byte == 0) break;      }}static void cmd_load(int id){      unsigned base1 = memory_map[id].control_regs[1];      unsigned size1 = memory_map[id].control_regs[2];      unsigned cnt;      char path[4096];      FILE*fd;      extract_path_from_load(path, id);      path[sizeof(path) - 1] = 0;      fd = fopen(path, "rb");      if (fd == NULL) {	    vpi_printf("MEM%d: Error opening %s for read\n", id, path);	    memory_map[id].control_regs[0] = -1;	    return;      }      cnt = fread(memory_map[id].base + base1, 1, size1, fd);      vpi_printf("MEM%d: Read %u bytes from %s to offset 0x%08x\n",		 id, cnt, path, base1);      memory_map[id].control_regs[0] = cnt;}static void cmd_save(int id){      unsigned base1 = memory_map[id].control_regs[1];      unsigned size1 = memory_map[id].control_regs[2];      unsigned cnt;      char path[sizeof(memory_map[id].control_regs)];      FILE*fd;      extract_path_from_load(path, id);      path[sizeof(path) - 1] = 0;      fd = fopen(path, "wb");      if (fd == NULL) {	    vpi_printf("MEM%d: Error opening %s for write\n", id, path);	    memory_map[id].control_regs[0] = -1;	    return;      }      cnt = fwrite(memory_map[id].base + base1, 1, size1, fd);      vpi_printf("MEM%d: Wrote %u bytes from offset 0x%08x to %s\n",		 id, cnt, base1, path);      memory_map[id].control_regs[0] = cnt;      fclose(fd);}static void memdev_command(int id){      switch (memory_map[id].control_regs[0]) {	  case CMD_FILL:	    cmd_fill(id);	    break;	  case CMD_COMPARE:	    cmd_compare(id);	    break;	  case CMD_LOAD:	    cmd_load(id);	    break;	  case CMD_SAVE:	    cmd_save(id);	    break;	  default:	    break;      }}static void init_fifo(void){      int rc;      if (cfd0 != 0)	    return;      rc = mkfifo(pci_fifo0, 0666);      if ((rc == -1) && (errno != EEXIST)) {	    perror(pci_fifo0);	    return;      }      rc = open(pci_fifo0, O_RDONLY, 0);      assert(rc >= 0);      cfd0 = fdopen(rc, "r");      rc = mkfifo(pci_fifo1, 0666);      if ((rc == -1) && (errno != EEXIST)) {	    perror(pci_fifo1);	    return;      }      rc = open(pci_fifo1, O_WRONLY, 0);      assert(rc >= 0);      cfd1 = fdopen(rc, "w");}static int cleanup(struct t_cb_data*cb){      if (cfd0) {	    fclose(cfd0);	    cfd0 = 0;      }      if (cfd1) {	    fclose(cfd1);	    cfd1 = 0;      }      unlink(pci_fifo0);      unlink(pci_fifo1);}static int master_command_compiletf(char*cd){      vpiHandle sys = vpi_handle(vpiSysTfCall, 0);      vpiHandle argv = vpi_iterate(vpiArgument, sys);      vpiHandle cmd, mem;	/* Make sure the first argument exists and is a reg. */      cmd = vpi_scan(argv);      assert(cmd);	/* Make sure the second argument exists and is a memory. */      mem = vpi_scan(argv);      assert(mem);      init_fifo();      return 0;}static int master_command_calltf(char*cd){      s_vpi_value value;      int rc;      char buf[1024], *cp;      unsigned long val[17];      unsigned word_addr;      unsigned idx;      vpiHandle sys = vpi_handle(vpiSysTfCall, 0);      vpiHandle argv = vpi_iterate(vpiArgument, sys);      vpiHandle cmd, mem, words, word;      cmd = vpi_scan(argv);      assert(cmd);      mem = vpi_scan(argv);      assert(mem);      word_addr = 0;      while (word_addr == 0) {	      /* Read from the command channel a string of numbers. */	    cp = fgets(buf, sizeof buf, cfd0);	    if (cp == 0) {		  vpi_printf("pci: ERROR communicating with remote.\n");		  vpi_free_object(argv);		  vpi_control(vpiStop, 0);		  return 0;	    }	    assert(cp);	    cp = buf + strspn(buf, " \t\r\n");	    word_addr = 0;	    while (*cp && (word_addr < 17)) {		  char*tmp;		  val[word_addr] = strtoul(cp, &tmp, 0);		  assert(tmp != cp);		  cp = tmp + strspn(tmp, " \t\r\n");		  word_addr += 1;	    }      }      value.format = vpiIntVal;      value.value.integer = val[0];      vpi_put_value(cmd, &value, 0, vpiNoDelay);	/* Iterate over the words in the memory, and get its values	   from the val[] array. */      words = vpi_iterate(vpiMemoryWord, mem);      assert(words);      idx = 1;      for (word = vpi_scan(words) ;  word ;  word = vpi_scan(words)) {	    unsigned long use_val;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -