📄 pci.c
字号:
/* * 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 + -