Example #1
0
/**
 * Set up a DMA transfer.
 * @param direction the direction of the transfer (DMA_READ or DMA_WRITE)
 * @param chan the channel
 * @param addr the address of the buffer
 * @param size number of bytes to transfer
 */
void Setup_DMA(enum DMA_Direction direction, int chan, void *addr_,
               ulong_t size) {
    uchar_t mode = 0;
    ulong_t addr = (ulong_t) addr_;

    /* Make sure parameters are sensible */
    KASSERT(direction == DMA_READ || direction == DMA_WRITE);
    KASSERT(VALID_CHANNEL(chan));
    KASSERT(IS_RESERVED(chan));
    KASSERT(VALID_MEM(addr, size));
    KASSERT(size > 0);
    /* elaborate because the otherwise working test wouldn't work if the DMA region was precisely 64K page aligned. */
    KASSERT0((((addr & 0xffff) == 0 && size <= 65536)) ||
             (size <= (0xffff - (addr & 0xffff))),
             "DMA region can't cross 64K boundary");

    /* Set up transfer mode */
    mode |= DMA_MODE_SINGLE;
    mode |= (direction == DMA_READ) ? DMA_MODE_READ : DMA_MODE_WRITE;
    mode |= (chan & 3);
    if (chan == 5)
        mode |= 0x10;           /* nspring testing, make this better if useful. */

    Debug("Setup_DMA(%s,%d,%x,%d)\n",
          direction == DMA_READ ? "DMA_READ" : "DMA_WRITE", chan, addr, size);
    Debug("Setup_DMA: mode=%02x\n", mode);
    Debug("DMA_ADDR_REG for channel is %02x\n", DMA_ADDR_REG(chan));
    Debug("DMA_PAGE_REG for channel is %02x\n", DMA_PAGE_REG(chan));
    Debug("DMA_COUNT_REG for channel is %02x\n", DMA_COUNT_REG(chan));

    /* Temporarily mask the DMA channel */
    Mask_DMA(chan);

    /* Write the transfer mode */
    Out_Byte(DMA_MODE_REG(chan), mode);

    /* Clear the byte pointer flip-flop */
    Out_Byte(DMA_CLEAR_FF_REG(chan), 0);        /* doesn't matter what value is written here */

    /* Write the transfer address (LSB, then MSB) */
    Out_Byte(DMA_ADDR_REG(chan), addr & 0xFF);
    Out_Byte(DMA_ADDR_REG(chan), (addr >> 8) & 0xFF);

    /* Write the page register */
    Out_Byte(DMA_PAGE_REG(chan), (addr >> 16) & 0xFF);

    /*
     * Write the count (LSB, then MSB)
     * Note that the count is one less that the number of bytes transferred
     */
    if (chan > 4) {
        size >>= 1;
    }                           /* words not bytes? */
Example #2
0
void load_and_simulate(const char *bin_fname)
{
  // Load binary into memory
  int fd = open(bin_fname, O_RDONLY);
  if (fd < 0) {
    fprintf(stderr, "Cannot open file %s\n", bin_fname);
    exit(-1);
  }
  size_t len = lseek(fd, 0, SEEK_END);
  void *data = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, 0);
  if (data == MAP_FAILED) {
    fprintf(stderr, "Memory map failed\n");
    close(fd);
    exit(-1);
  }

  // FIXME:: How big is our memory?? -- 512MB
  // FIXME:: What is the format of binary? ELF?? -- Just full mem-image
  // FIXME:: where is the program start address -- at 0x0
  // FIXME:: Where to load the binary -- at 0x0
  const size_t mem_size = ((size_t)512)*1024*1024;
  const size_t load_pos = (size_t)0x0;
  const size_t start_pos = (size_t)0x0;

  int32_t *mem = (int32_t*)memalign(4096, mem_size);

  if (!mem) {
    fprintf(stderr, "Cannot allocate memory\n");
    munmap(data, len);
    close(fd);
    exit(-1);
  }
  // Load data to 0x1000
  memcpy(&mem[load_pos], data, len);

  munmap(data, len);
  close(fd);

#define VALID_MEM(X) \
  ((X) >= 0 && (X) <= (mem_size - sizeof(int32_t)))
#define VALID_PC(X) \
  ((X) >= 0 && (X) <= (mem_size - sizeof(int32_t)*3))
  // Start executing --
  // All our instructions are subleq A, B, C
  // From wikipedia: https://en.wikipedia.org/wiki/One_instruction_set_computer
  // subleq A, B, C: Mem[B] = Mem[B] - Mem[A]
  //                 if (Mem[B] <= 0) goto C
  int32_t pc = (int32_t)start_pos;
  while (VALID_PC(pc)) {
    int32_t A = mem[pc];
    int32_t B = mem[pc+1];
    int32_t C = mem[pc+2];
    printf("%8x: %8x %8x %8x: A=%d B=%d\n",pc, A, B, C,
           VALID_MEM(A)?mem[A]:0, VALID_MEM(B)?mem[B]:0);

    if (A < 0 || B < 0) {
      pc = 0;
      continue;
    }
    mem[B] -= mem[A];
    if (mem[B] > 0) {
      pc += 3;
    } else {
      pc = C;
    }
  }

  // clean up
  free(mem);
}