예제 #1
0
void return_command_block_data(){

  vpiHandle systfref, args_iter, argh;

  struct t_vpi_value argval;

  int value,i;

  int n;

  uint32_t data;
  uint32_t length;

  char *block_data_buf;
  uint32_t *block_word_data_buf_ptr;

  int num_words;
  int sent_words = 0;

  vpiHandle array_word;
  
  // Now setup the handles to verilog objects and check things
  // Obtain a handle to the argument list
  systfref = vpi_handle(vpiSysTfCall, NULL);
  
  // Now call iterate with the vpiArgument parameter
  args_iter = vpi_iterate(vpiArgument, systfref); 
  
  // get a handle on the length variable
  argh = vpi_scan(args_iter);
  
  argval.format = vpiIntVal;
  
  // get the value for the length object
  vpi_get_value(argh, &argval);

  // now set length
  length = argval.value.integer;

  // now get a handle on the next object (memory array)
  argh = vpi_scan(args_iter);

  // check we got passed a memory (array of regs) (modelsim passes back a vpiRegArray, so check for that too)
  if (!((vpi_get(vpiType, argh) == vpiMemory) 
#ifdef MODELSIM_VPI
	|| (vpi_get(vpiType, argh) == vpiRegArray)
#endif
      ))
    { 
      vpi_printf("jp_vpi: ERROR: did not pass a memory to return_command_block_data\n");
      vpi_printf("jp_vpi: ERROR: was passed type %d\n", (int)vpi_get(vpiType, argh));
      return;
    }
  
  // We have to alloc memory here for lengths > 4
  if (length > 4);
  {
    block_data_buf = (char*) malloc(length * sizeof(char));
    if (block_data_buf == NULL)
      {
	vpi_printf("jp_vpi: return_command_block_data: Error. Could not allocate memory\n");
	// Cleanup and return
	vpi_free_object(args_iter);
	return;
      }

    // Now cast it as a uint32_t array
    block_word_data_buf_ptr = (uint32_t *) block_data_buf;
  }

  num_words = length / 4; // We're always going to be dealing with whole words here
  
  if (DBG_JP_VPI) printf("jp_vpi: return_command_block_data: num_words %d\n",
			 num_words);

    // Loop to load the words
  while (sent_words < num_words) {
    
    // Get a handle on the current word we want in the array that was passed to us
    array_word = vpi_handle_by_index(argh, sent_words);
    
    if (array_word != NULL)
      {
	vpi_get_value(array_word, &argval);
	
	data = (uint32_t) argval.value.integer;
	
	block_word_data_buf_ptr[sent_words] = data;
      }
    else
      return;

    if (DBG_JP_VPI) printf ( "jp_vpi: return_command_block_data: word %d 0x%.8x\n",
			     sent_words, data);
    sent_words++;
  }
  
  if (!(length > 4))
    {
      block_data_buf = (char *) &data; 
    }
  
  n = write(vpi_to_rsp_pipe[1],block_data_buf,length);

  
  if (length > 4)
    {
      // Free the array
      free(block_data_buf);
    }
    
  
  // Cleanup and return
  vpi_free_object(args_iter);

  return;

}
예제 #2
0
static void scan_item(unsigned depth, vpiHandle item, int skip)
{
      struct t_cb_data cb;
      struct vcd_info* info;

      const char* name;
      const char* ident;
      int nexus_id;

      /* list of types to iterate upon */
      int i;
      static int types[] = {
	    /* Value */
	    vpiNet,
	    vpiReg,
	    vpiVariables,
	    /* Scope */
	    vpiFunction,
	    vpiModule,
	    vpiNamedBegin,
	    vpiNamedFork,
	    vpiTask,
	    -1
      };

      switch (vpi_get(vpiType, item)) {

	  case vpiMemoryWord:
	    if (vpi_get(vpiConstantSelect, item) == 0) {
		    /* Turn a non-constant array word select into a
		     * constant word select. */
		  vpiHandle array = vpi_handle(vpiParent, item);
		  PLI_INT32 idx = vpi_get(vpiIndex, item);
		  item = vpi_handle_by_index(array, idx);
	    }
	  case vpiIntegerVar:
	  case vpiBitVar:
	  case vpiByteVar:
	  case vpiShortIntVar:
	  case vpiIntVar:
	  case vpiLongIntVar:
	  case vpiTimeVar:
	  case vpiReg:
	  case vpiNet:

	      /* An array word is implicitly escaped so look for an
	       * escaped identifier that this could conflict with. */
            if (vpi_get(vpiType, item) == vpiMemoryWord &&
                vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) {
		  vpi_printf("LXT warning: dumping array word %s will "
		             "conflict with an escaped identifier.\n",
		             vpi_get_str(vpiFullName, item));
            }

            if (skip || vpi_get(vpiAutomatic, item)) break;

	    name = vpi_get_str(vpiName, item);
	    nexus_id = vpi_get(_vpiNexusId, item);
	    if (nexus_id) {
		  ident = find_nexus_ident(nexus_id);
	    } else {
		  ident = 0;
	    }

	    if (!ident) {
		  char*tmp = create_full_name(name);
		  ident = strdup_sh(&name_heap, tmp);
		  free(tmp);

		  if (nexus_id) set_nexus_ident(nexus_id, ident);

		  info = malloc(sizeof(*info));

		  info->time.type = vpiSimTime;
		  info->item  = item;
		  info->sym   = lt_symbol_add(dump_file, ident,
		                              0 /* array rows */,
		                              vpi_get(vpiLeftRange, item),
		                              vpi_get(vpiRightRange, item),
		                              LT_SYM_F_BITS);
		  info->scheduled = 0;

		  cb.time      = &info->time;
		  cb.user_data = (char*)info;
		  cb.value     = NULL;
		  cb.obj       = item;
		  cb.reason    = cbValueChange;
		  cb.cb_rtn    = variable_cb_1;

		  info->next  = vcd_list;
		  vcd_list    = info;

		  info->cb    = vpi_register_cb(&cb);

	    } else {
		  char *n = create_full_name(name);
		  lt_symbol_alias(dump_file, ident, n,
				  vpi_get(vpiSize, item)-1, 0);
		  free(n);
            }

	    break;

	  case vpiRealVar:

            if (skip || vpi_get(vpiAutomatic, item)) break;

	    name = vpi_get_str(vpiName, item);
	    { char*tmp = create_full_name(name);
	      ident = strdup_sh(&name_heap, tmp);
	      free(tmp);
	    }
	    info = malloc(sizeof(*info));

	    info->time.type = vpiSimTime;
	    info->item = item;
	    info->sym  = lt_symbol_add(dump_file, ident,
	                               0 /* array rows */,
	                               vpi_get(vpiSize, item)-1,
	                               0, LT_SYM_F_DOUBLE);
	    info->scheduled = 0;

	    cb.time      = &info->time;
	    cb.user_data = (char*)info;
	    cb.value     = NULL;
	    cb.obj       = item;
	    cb.reason    = cbValueChange;
	    cb.cb_rtn    = variable_cb_1;

	    info->next  = vcd_list;
	    vcd_list    = info;

	    info->cb    = vpi_register_cb(&cb);

	    break;

	  case vpiModule:
	  case vpiNamedBegin:
	  case vpiTask:
	  case vpiFunction:
	  case vpiNamedFork:

	    if (depth > 0) {
		  int nskip;
		  vpiHandle argv;

		  const char* fullname =
			vpi_get_str(vpiFullName, item);

#if 0
		  vpi_printf("LXT info: scanning scope %s, %u levels\n",
		             fullname, depth);
#endif
		  nskip = 0 != vcd_names_search(&lxt_tab, fullname);

		  if (!nskip)
			vcd_names_add(&lxt_tab, fullname);
		  else
		    vpi_printf("LXT warning: ignoring signals in "
		               "previously scanned scope %s\n", fullname);

		  name = vpi_get_str(vpiName, item);

                  push_scope(name);

		  for (i=0; types[i]>0; i++) {
			vpiHandle hand;
			argv = vpi_iterate(types[i], item);
			while (argv && (hand = vpi_scan(argv))) {
			      scan_item(depth-1, hand, nskip);
			}
		  }

                  pop_scope();
	    }
	    break;

	  default:
	    vpi_printf("LXT warning: $dumpvars: Unsupported parameter "
	               "type (%s)\n", vpi_get_str(vpiType, item));
      }

}
예제 #3
0
void get_command_block_data(){ // $get_command_block_data(length, mem_array)

  vpiHandle systfref, args_iter, argh;

  struct t_vpi_value argval;

  int value,i;

  int n;

  uint32_t data;
  uint32_t length;

  char* recv_buf;

  // Now setup the handles to verilog objects and check things
  // Obtain a handle to the argument list
  systfref = vpi_handle(vpiSysTfCall, NULL);
  
  // Now call iterate with the vpiArgument parameter
  args_iter = vpi_iterate(vpiArgument, systfref); 
  
  // get a handle on the length variable
  argh = vpi_scan(args_iter);
  
  argval.format = vpiIntVal;
  
  // get the value for the length object
  vpi_get_value(argh, &argval);

  // now set length
  length = argval.value.integer;

  int num_words = length/4;
  
  //if((length % 4) != 0) vpi_printf("length of %d bytes is not exactly word-aligned\n",length);
  // If non-word aligned we throw away remainder
  int throw_away_bytes = length %4;

  int loaded_words = 0;

  if(DBG_JP_VPI)printf("jp_vpi: get_command_block_data: length=%d, num_words=%d\n",length,num_words);

  // now get a handle on the next object (memory array)
  argh = vpi_scan(args_iter);

  // check we got passed a memory (array of regs)
  if (!((vpi_get(vpiType, argh) == vpiMemory) 
#ifdef MODELSIM_VPI
	|| (vpi_get(vpiType, argh) == vpiRegArray)
#endif
	))
    { 
      vpi_printf("jp_vpi: ERROR: did not pass a memory to get_command_block_data\n");
      vpi_printf("jp_vpi: ERROR: was passed type %d\n", (int)vpi_get(vpiType, argh));
      return;
    }
  
  // check the memory we're writing into is big enough
  if (vpi_get(vpiSize, argh) < num_words ) 
    {
      vpi_printf("jp_vpi: ERROR: buffer passed to get_command_block_data too small. size is %d words, needs to be %d\n",
		 vpi_get(vpiSize, argh), num_words);
      return;
    } 
  
  vpiHandle array_word;

  // Loop to load the words
  while (loaded_words < num_words) {
    
    recv_buf = (char *) &data;
    
    // blocking receive for data block
    n = read(rsp_to_vpi_pipe[0],recv_buf,4);
    
    // now get a handle on the current word we want in the array that was passed to us
    array_word = vpi_handle_by_index(argh, loaded_words);
    
    if (array_word != NULL)
      {
	argval.value.integer = (uint32_t) data;
	
	// And vpi_put_value() it back into the sim
	vpi_put_value(array_word, &argval, NULL, vpiNoDelay);
      }
    else
      return;
    
    loaded_words++;
  }
  // TODO: This is a quick fix, should be delt with properly!!
  if (throw_away_bytes) 
    {
      //printf("reading off %d extra data bytes\n",throw_away_bytes);
      n = read(rsp_to_vpi_pipe[0],&data,throw_away_bytes);
      //printf("read off %d bytes \n",n);
    }
  
  // Cleanup and return
  vpi_free_object(args_iter);
  
  return;

}
예제 #4
0
static PLI_INT32 sys_writemem_calltf(PLI_BYTE8*name)
{
    int wwid;
    char*path;
    char*mem_name;
    FILE*file;
    unsigned addr = 0;
    unsigned cnt = 0;
    s_vpi_value value;
    vpiHandle words;
    vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
    vpiHandle argv = vpi_iterate(vpiArgument, sys);
    vpiHandle item = vpi_scan(argv);
    vpiHandle mitem;
    vpiHandle start_item;
    vpiHandle stop_item;
    vpiHandle word_index;
    vpiHandle left_range;
    vpiHandle right_range;

    int left_addr, right_addr;
    int start_addr, stop_addr, addr_incr;
    int min_addr, max_addr;

    /*======================================== Get parameters */

    if (item == 0) {
        vpi_printf("%s: file name parameter missing.\n", name);
        return 0;
    }

    if (vpi_get(vpiType, item) != vpiConstant) {
        vpi_printf("ERROR: %s parameter must be a constant\n", name);
        vpi_free_object(argv);
        return 0;
    }

    if (vpi_get(vpiConstType, item) != vpiStringConst) {
        vpi_printf("ERROR: %s parameter must be a string\n", name);
        vpi_free_object(argv);
        return 0;
    }

    value.format = vpiStringVal;
    vpi_get_value(item, &value);
    path = strdup(value.value.str);

    /* Get and check the second parameter. It must be a memory. */
    mitem = vpi_scan(argv);
    if (mitem == 0) {
        vpi_printf("%s: Missing memory parameter\n", name);
        free(path);
        return 0;
    }

    if (vpi_get(vpiType, mitem) != vpiMemory) {
        vpi_printf("%s: Second parameter must be a memory.\n", name);
        free(path);
        vpi_free_object(argv);
        return 0;
    }

    mem_name = vpi_get_str(vpiFullName, mitem);

    /* Get optional third parameter. It must be a constant. */
    start_item = vpi_scan(argv);
    if (start_item!=0) {
        if (check_integer_constant(name, start_item) == 0) {
            vpi_free_object(argv);
            return 0;
        }

        /* Get optional forth parameter. It must be a constant. */
        stop_item = vpi_scan(argv);
        if (stop_item!=0) {
            if (check_integer_constant(name, stop_item) == 0) {
                vpi_free_object(argv);
                return 0;
            }

            /* Check that there is no 5th parameter */
            if (vpi_scan(argv) != 0) {
                vpi_printf("ERROR: %s accepts maximum 4 parameters!\n", name );
                vpi_free_object(argv);
                return 0;
            }

        }
    }
    else {
        stop_item = 0;
    }

    /*======================================== Process parameters */

    /* Open the data file. */
    file = fopen(path, "w");
    if (file == 0) {
        vpi_printf("%s: Unable to open %s for writing.\n", name, path);
        free(path);
        return 0;
    }

    /* Get left addr of memory */
    left_range = vpi_handle(vpiLeftRange, mitem);
    value.format = vpiIntVal;
    vpi_get_value(left_range, &value);
    left_addr = value.value.integer;

    /* Get right addr of memory */
    right_range = vpi_handle(vpiRightRange, mitem);
    value.format = vpiIntVal;
    vpi_get_value(right_range, &value);
    right_addr = value.value.integer;

    /* Get start_addr, stop_addr and addr_incr */
    if (start_item==0) {
        start_addr = left_addr<right_addr ? left_addr  : right_addr;
        stop_addr  = left_addr<right_addr ? right_addr : left_addr;
        addr_incr = 1;
    }
    else {
        s_vpi_value value2;
        value2.format = vpiIntVal;
        vpi_get_value(start_item, &value2);
        start_addr = value2.value.integer;

        if (stop_item==0) {
            stop_addr = left_addr<right_addr ? right_addr : left_addr;
            addr_incr = 1;
        }
        else {
            s_vpi_value value3;
            value3.format = vpiIntVal;
            vpi_get_value(stop_item, &value3);
            stop_addr = value3.value.integer;

            addr_incr = start_addr<stop_addr ? 1 : -1;
        }
    }

    min_addr = start_addr<stop_addr ? start_addr : stop_addr ;
    max_addr = start_addr<stop_addr ? stop_addr  : start_addr;

    /* Check that start_addr and stop_addr are within the memory
    range */
    if (left_addr<right_addr) {
        if (start_addr<left_addr || start_addr > right_addr) {
            vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name);
            return 0;
        }

        if (stop_addr<left_addr || stop_addr > right_addr) {
            vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name);
            return 0;
        }
    }
    else {
        if (start_addr<right_addr || start_addr > left_addr) {
            vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name);
            return 0;
        }

        if (stop_addr<right_addr || stop_addr > left_addr) {
            vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name);
            return 0;
        }
    }


    words = vpi_iterate(vpiMemoryWord, mitem);
    assert(words);

    item = vpi_scan(words);
    wwid = vpi_get(vpiSize, item);

    if (strcmp(name,"$writememb")==0) {
        value.format = vpiBinStrVal;
    }
    else {
        value.format = vpiHexStrVal;
    }

    /*======================================== Write memory file */

    cnt=0;
    for(addr=start_addr; addr!=stop_addr+addr_incr; addr+=addr_incr, ++cnt) {
        if (cnt%16 == 0)
            fprintf(file, "// 0x%08x\n", cnt);

        word_index = vpi_handle_by_index(mitem, addr);
        assert(word_index);
        vpi_get_value(word_index, &value);
        fprintf(file, "%s\n", value.value.str);
    }

    fclose(file);
    return 0;
}
예제 #5
0
static PLI_INT32 sys_readmem_calltf(PLI_BYTE8*name)
{
    int code;
    int wwid;
    char*path;
    char*mem_name;
    FILE*file;
    unsigned addr;
    s_vpi_value value;
    vpiHandle sys = vpi_handle(vpiSysTfCall, 0);
    vpiHandle argv = vpi_iterate(vpiArgument, sys);
    vpiHandle item = vpi_scan(argv);
    vpiHandle mitem;
    vpiHandle start_item;
    vpiHandle stop_item;
    vpiHandle left_range;
    vpiHandle right_range;
    vpiHandle word_index;

    /* These are left and right hand side parameters in the
    declaration of the memory. */
    int left_addr, right_addr;

    /* start_addr and stop_addr are the parameters given to $readmem in the
    Verilog code. When not specified, start_addr is equal to the lower of
     the [left,right]_addr and stop_addr is equal to the higher of the
     [left,right]_addr. */
    int start_addr, stop_addr, addr_incr;

    /* min_addr and max_addr are equal to start_addr and stop_addr if
    start_addr<stop_addr or vice versa if not... */
    unsigned min_addr, max_addr;

    /* This is the number of words that we need from the memory. */
    unsigned word_count;


    /*======================================== Get parameters */

    if (item == 0) {
        vpi_printf("%s: file name parameter missing.\n", name);
        return 0;
    }

    /* Check then get the first argument, the file name. It is
       possible that Verilog would right-justify a name to fit a
       reg value to fit the reg width, so chop off leading white
       space in the process. */
    if (check_file_name(name, item) == 0) {
        vpi_free_object(argv);
        return 0;
    }

    value.format = vpiStringVal;
    vpi_get_value(item, &value);
    path = strdup(value.value.str + strspn(value.value.str, " "));

    /* Get and check the second parameter. It must be a memory. */
    mitem = vpi_scan(argv);
    if (mitem == 0) {
        vpi_printf("%s: Missing memory parameter\n", name);
        free(path);
        return 0;
    }

    if (vpi_get(vpiType, mitem) != vpiMemory) {
        vpi_printf("%s: Second parameter must be a memory.\n", name);
        free(path);
        vpi_free_object(argv);
        return 0;
    }

    mem_name = vpi_get_str(vpiFullName, mitem);

    /* Get optional third parameter. It must be a constant. */
    start_item = vpi_scan(argv);
    if (start_item!=0) {
        if (check_integer_constant(name, start_item) == 0) {
            vpi_free_object(argv);
            return 0;
        }

        /* Get optional forth parameter. It must be a constant. */
        stop_item = vpi_scan(argv);
        if (stop_item!=0) {
            if (check_integer_constant(name, stop_item) == 0) {
                vpi_free_object(argv);
                return 0;
            }

            /* Check that there is no 5th parameter */
            if (vpi_scan(argv) != 0) {
                vpi_printf("ERROR: %s accepts maximum 4 parameters!\n", name );
                vpi_free_object(argv);
                return 0;
            }

        }
    }
    else {
        stop_item = 0;
    }

    /*======================================== Process parameters */

    /* Open the data file. */
    file = fopen(path, "r");
    if (file == 0) {
        vpi_printf("%s: Unable to open %s for reading.\n", name, path);
        free(path);
        return 0;
    }

    /* Get left addr of memory */
    left_range = vpi_handle(vpiLeftRange, mitem);
    value.format = vpiIntVal;
    vpi_get_value(left_range, &value);
    left_addr = value.value.integer;

    /* Get right addr of memory */
    right_range = vpi_handle(vpiRightRange, mitem);
    value.format = vpiIntVal;
    vpi_get_value(right_range, &value);
    right_addr = value.value.integer;

    /* Get start_addr, stop_addr and addr_incr */
    if (start_item==0) {
        start_addr = left_addr<right_addr ? left_addr  : right_addr;
        stop_addr  = left_addr<right_addr ? right_addr : left_addr;
        addr_incr = 1;
    }
    else {
        s_vpi_value value2;
        value2.format = vpiIntVal;
        vpi_get_value(start_item, &value2);
        start_addr = value2.value.integer;

        if (stop_item==0) {
            stop_addr = left_addr<right_addr ? right_addr : left_addr;
            addr_incr = 1;
        }
        else {
            s_vpi_value value3;
            value3.format = vpiIntVal;
            vpi_get_value(stop_item, &value3);
            stop_addr = value3.value.integer;

            addr_incr = start_addr<stop_addr ? 1 : -1;
        }
    }

    min_addr = start_addr<stop_addr ? start_addr : stop_addr ;
    max_addr = start_addr<stop_addr ? stop_addr  : start_addr;

    /* We need this many words from the file. */
    word_count = max_addr-min_addr+1;

    /* Check that start_addr and stop_addr are within the memory
    range */
    if (left_addr<right_addr) {
        if (start_addr<left_addr || start_addr > right_addr) {
            vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name);
            return 0;
        }

        if (stop_addr<left_addr || stop_addr > right_addr) {
            vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name);
            return 0;
        }
    }
    else {
        if (start_addr<right_addr || start_addr > left_addr) {
            vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name);
            return 0;
        }

        if (stop_addr<right_addr || stop_addr > left_addr) {
            vpi_printf("%s: Stop address is out of bounds for memory \'%s\'!\n", name, mem_name);
            return 0;
        }
    }

    item = vpi_handle_by_index(mitem,min_addr);
    wwid = vpi_get(vpiSize, item);

    /* variable that will be uses by the lexer to pass values
    back to this code */
    value.format = vpiVectorVal;
    value.value.vector = calloc((wwid+31)/32, sizeof(s_vpi_vecval));

    /* Configure the readmem lexer */
    if (strcmp(name,"$readmemb") == 0)
        sys_readmem_start_file(file, 1, wwid, value.value.vector);
    else
        sys_readmem_start_file(file, 0, wwid, value.value.vector);


    /*======================================== Read memory file */

    /* Run through the input file and store the new contents in the memory */
    addr = start_addr;
    while ((code = readmemlex()) != 0) {
        switch (code) {
        case MEM_ADDRESS:
            addr = value.value.vector->aval;
            /* if there is an address in the memory file, then
               turn off any possible warnings about not having
               enough words to load the memory. This is standard
               behavior. */
            word_count = 0;
            break;

        case MEM_WORD:
            if (addr >= min_addr && addr <= max_addr) {
                word_index = vpi_handle_by_index(mitem, addr);
                assert(word_index);
                vpi_put_value(word_index, &value, 0, vpiNoDelay);

                if (word_count > 0)
                    word_count -= 1;
            }
            else {
                vpi_printf("%s(%s): address (0x%x) out of range (0x%x:0x%x)\n",
                           name, path, addr, start_addr, stop_addr);
                goto bailout;
            }

            addr += addr_incr;
            break;

        default:
            vpi_printf("Huh?! (%d)\n", code);
            break;
        }
    }

    if (word_count > 0)
        vpi_printf("%s(%s): Not enough words in the read file "
                   "for requested range.\n", name, path);

bailout:
    free(value.value.vector);
    free(path);
    fclose(file);
    return 0;
}
예제 #6
0
void send_result_to_server(char *userdata){

	vpiHandle systfref, args_iter, argh;
	struct t_vpi_value argval;
	int n;
	struct vpi_cmd vpi;

	uint32_t length;
	int sent_words;

	vpiHandle array_word;

	// Now setup the handles to verilog objects and check things
	// Obtain a handle to the argument list
	systfref = vpi_handle(vpiSysTfCall, NULL);

	// Now call iterate with the vpiArgument parameter
	args_iter = vpi_iterate(vpiArgument, systfref);

	// get a handle on the length variable
	argh = vpi_scan(args_iter);

	argval.format = vpiIntVal;

	// get the value for the length object
	vpi_get_value(argh, &argval);

	// now set length
	length = argval.value.integer;

	// now get a handle on the next object (memory array)
	argh = vpi_scan(args_iter);

	// check we got passed a memory (array of regs)
	if (!((vpi_get(vpiType, argh) == vpiMemory)
#ifdef MODELSIM_VPI
	|| (vpi_get(vpiType, argh) == vpiRegArray)
#endif
	)) {
		vpi_printf("jp_vpi: ERROR: did not pass a memory to get_command_block_data\n");
		vpi_printf("jp_vpi: ERROR: was passed type %d\n", (int)vpi_get(vpiType, argh));
		return;
	}

	// check the memory we're writing into is big enough
	if (vpi_get(vpiSize, argh) < length ) {
		vpi_printf("jp_vpi: ERROR: buffer passed to get_command_block_data too small. size is %d words, needs to be %d\n",
		 vpi_get(vpiSize, argh), length);
		return;
	}

	// Loop to load the words
	sent_words = 0;
	while (sent_words < length) {
		// Get a handle on the current word we want in the array that was passed to us
		array_word = vpi_handle_by_index(argh, sent_words);

		if (array_word != NULL) {
			vpi_get_value(array_word, &argval);
			vpi.buffer_in[sent_words] = (uint32_t) argval.value.integer;
		} else
			return;

		sent_words++;
	}

	n = write(connfd, &vpi, sizeof(struct vpi_cmd));

	// Cleanup and return
	vpi_free_object(args_iter);
}
예제 #7
0
void check_for_command(char *userdata)
{
	vpiHandle systfref, args_iter, argh;
	struct t_vpi_value argval;
	struct vpi_cmd vpi;
	int nb;
	int loaded_words = 0;

	// Get the command from TCP server

	nb = read(connfd, &vpi, sizeof(struct vpi_cmd));

	if (((nb < 0) && (errno == EAGAIN)) || (nb == 0)) {
		// Nothing in the fifo this time, let's return
		return;
	} else {
		if (nb < 0) {
			// some sort of error
			perror("check_for_command");
			exit(1);
		}
	}
/*
	printf("\nReceived command:\n");
	printf("cmd     = %s\n", cmd_to_string[vpi.cmd]);
	printf("length  = %d\n", vpi.length);
	if (vpi.length) {
		printf("nb_bits = %d\n", vpi.nb_bits);
		printf("buffer  = ");
		for (i = 0; i < vpi.length; i++)
			printf("%02X ", vpi.buffer_out[i]);
		printf("\n");
	}
*/
/************* vpi.cmd to VPI ******************************/

	// Obtain a handle to the argument list
	systfref = vpi_handle(vpiSysTfCall, NULL);
	// Now call iterate with the vpiArgument parameter
	args_iter = vpi_iterate(vpiArgument, systfref);
	// get a handle on the variable passed to the function
	argh = vpi_scan(args_iter);
	// now store the command value back in the sim
	argval.format = vpiIntVal;
	// Now set the command value
	vpi_get_value(argh, &argval);

	argval.value.integer = (uint32_t)vpi.cmd;

	// And vpi_put_value() it back into the sim
	vpi_put_value(argh, &argval, NULL, vpiNoDelay);

/************* vpi.length to VPI ******************************/

	// now get a handle on the next object (memory array)
	argh = vpi_scan(args_iter);
	// now store the command value back in the sim
	argval.format = vpiIntVal;
	// Now set the command value
	vpi_get_value(argh, &argval);

	argval.value.integer = (uint32_t)vpi.length;

	// And vpi_put_value() it back into the sim
	vpi_put_value(argh, &argval, NULL, vpiNoDelay);

/************* vpi.nb_bits to VPI ******************************/

	// now get a handle on the next object (memory array)
	argh = vpi_scan(args_iter);
	// now store the command value back in the sim
	argval.format = vpiIntVal;
	// Now set the command value
	vpi_get_value(argh, &argval);

	argval.value.integer = (uint32_t)vpi.nb_bits;

	// And vpi_put_value() it back into the sim
	vpi_put_value(argh, &argval, NULL, vpiNoDelay);

/*****************vpi.buffer_out to VPI ********/

	// now get a handle on the next object (memory array)
	argh = vpi_scan(args_iter);
	vpiHandle array_word;

	// Loop to load the words
	while (loaded_words < vpi.length) {
		// now get a handle on the current word we want in the array that was passed to us
		array_word = vpi_handle_by_index(argh, loaded_words);

		if (array_word != NULL) {
			argval.value.integer = (uint32_t)vpi.buffer_out[loaded_words];
			// And vpi_put_value() it back into the sim
			vpi_put_value(array_word, &argval, NULL, vpiNoDelay);
		} else
			return;

		loaded_words++;
	}

/*******************************************/

	// Cleanup and return
	vpi_free_object(args_iter);

}
예제 #8
0
static void scan_item(unsigned depth, vpiHandle item, int skip)
{
      struct t_cb_data cb;
      struct vcd_info* info;

      enum fstVarType type = FST_VT_MAX;
      enum fstScopeType stype = FST_ST_MAX;
      enum fstVarDir dir;
      const char *name;
      const char *fullname;
      char *escname;
      const char *ident;
      fstHandle new_ident;
      int nexus_id;
      unsigned size;
      PLI_INT32 item_type;

	/* Get the displayed type for the various $var and $scope types. */
	/* Not all of these are supported now, but they should be in a
	 * future development version. */
      item_type = vpi_get(vpiType, item);
      switch (item_type) {
	  case vpiNamedEvent: type = FST_VT_VCD_EVENT; break;
	  case vpiIntVar:
	  case vpiIntegerVar: type = FST_VT_VCD_INTEGER; break;
	  case vpiParameter:  type = FST_VT_VCD_PARAMETER; break;
	    /* Icarus converts realtime to real. */
	  case vpiRealVar:    type = FST_VT_VCD_REAL; break;
	  case vpiMemoryWord:
	  case vpiBitVar:
	  case vpiByteVar:
	  case vpiShortIntVar:
	  case vpiLongIntVar:
	  case vpiReg:        type = FST_VT_VCD_REG; break;
	    /* Icarus converts a time to a plain register. */
	  case vpiTimeVar:    type = FST_VT_VCD_TIME; break;
	  case vpiNet:
	    switch (vpi_get(vpiNetType, item)) {
		case vpiWand:    type = FST_VT_VCD_WAND; break;
		case vpiWor:     type = FST_VT_VCD_WOR; break;
		case vpiTri:     type = FST_VT_VCD_TRI; break;
		case vpiTri0:    type = FST_VT_VCD_TRI0; break;
		case vpiTri1:    type = FST_VT_VCD_TRI1; break;
		case vpiTriReg:  type = FST_VT_VCD_TRIREG; break;
		case vpiTriAnd:  type = FST_VT_VCD_TRIAND; break;
		case vpiTriOr:   type = FST_VT_VCD_TRIOR; break;
		case vpiSupply1: type = FST_VT_VCD_SUPPLY1; break;
		case vpiSupply0: type = FST_VT_VCD_SUPPLY0; break;
		default:         type = FST_VT_VCD_WIRE; break;
	    }
	    break;

	  case vpiNamedBegin: stype = FST_ST_VCD_BEGIN; break;
	  case vpiNamedFork:  stype = FST_ST_VCD_FORK; break;
	  case vpiFunction:   stype = FST_ST_VCD_FUNCTION; break;
	  case vpiGenScope:   stype = FST_ST_VCD_GENERATE; break;
	  case vpiModule:     stype = FST_ST_VCD_MODULE; break;
	  case vpiTask:       stype = FST_ST_VCD_TASK; break;

	  default:
	    vpi_printf("FST warning: $dumpvars: Unsupported argument "
	               "type (%s)\n", vpi_get_str(vpiType, item));
	    return;
      }

	/* Do some special processing/checking on array words. Dumping
	 * array words is an Icarus extension. */
      if (item_type == vpiMemoryWord) {
	      /* Turn a non-constant array word select into a constant
	       * word select. */
	    if (vpi_get(vpiConstantSelect, item) == 0) {
		  vpiHandle array = vpi_handle(vpiParent, item);
		  PLI_INT32 idx = vpi_get(vpiIndex, item);
		  item = vpi_handle_by_index(array, idx);
	    }

	      /* An array word is implicitly escaped so look for an
	       * escaped identifier that this could conflict with. */
	      /* This does not work as expected since we always find at
	       * least the array word. We likely need a custom routine. */
            if (vpi_get(vpiType, item) == vpiMemoryWord &&
                vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) {
		  vpi_printf("FST warning: array word %s will conflict "
		             "with an escaped identifier.\n",
		             vpi_get_str(vpiFullName, item));
            }
      }

      fullname = vpi_get_str(vpiFullName, item);

	/* Generate the $var or $scope commands. */
      switch (item_type) {
	  case vpiParameter:
	    vpi_printf("FST sorry: $dumpvars: can not dump parameters.\n");
	    break;

	  case vpiNamedEvent:
	  case vpiIntegerVar:
	  case vpiBitVar:
	  case vpiByteVar:
	  case vpiShortIntVar:
	  case vpiIntVar:
	  case vpiLongIntVar:
	  case vpiRealVar:
	  case vpiMemoryWord:
	  case vpiReg:
	  case vpiTimeVar:
	  case vpiNet:

	      /* If we are skipping all signal or this is in an automatic
	       * scope then just return. */
            if (skip || vpi_get(vpiAutomatic, item)) return;

	      /* Skip this signal if it has already been included.
	       * This can only happen for implicitly given signals. */
	    if (vcd_names_search(&fst_var, fullname)) return;

	      /* Declare the variable in the FST file. */
	    name = vpi_get_str(vpiName, item);
	    if (is_escaped_id(name)) {
		  escname = malloc(strlen(name) + 2);
		  sprintf(escname, "\\%s", name);
	    } else escname = strdup(name);

	      /* Some signals can have an alias so handle that. */
	    nexus_id = vpi_get(_vpiNexusId, item);

	    ident = 0;
	    if (nexus_id) ident = find_nexus_ident(nexus_id);

	      /* Named events do not have a size, but other tools use
	       * a size of 1 and some viewers do not accept a width of
	       * zero so we will also use a width of one for events. */
	    if (item_type == vpiNamedEvent) size = 1;
	    else size = vpi_get(vpiSize, item);
	      /* The FST format supports a port direction so if the net
	       * is a port set the direction to one of the following:
	       *   FST_VD_INPUT, FST_VD_OUTPUT or FST_VD_INOUT */
	    dir = FST_VD_IMPLICIT;

	    if (size > 1 || vpi_get(vpiLeftRange, item) != 0) {
		  char *buf = malloc(strlen(escname) + 65);
		  sprintf(buf, "%s [%i:%i]", escname,
                            (int)vpi_get(vpiLeftRange, item),
                            (int)vpi_get(vpiRightRange, item));

		  new_ident = fstWriterCreateVar(dump_file, type,
		                                 dir, size, buf,
		                                 (fstHandle)(intptr_t)ident);
		  free(buf);
	    } else {
		  new_ident = fstWriterCreateVar(dump_file, type,
		                                 dir, size, escname,
		                                 (fstHandle)(intptr_t)ident);
	    }
	    free(escname);

	    if (!ident) {
		  if (nexus_id) set_nexus_ident(nexus_id,
		                                (const char *)(intptr_t)new_ident);

		    /* Add a callback for the signal. */
		  info = malloc(sizeof(*info));

		  info->time.type = vpiSimTime;
		  info->item  = item;
		  info->handle = new_ident;
		  info->scheduled = 0;

		  cb.time      = &info->time;
		  cb.user_data = (char*)info;
		  cb.value     = NULL;
		  cb.obj       = item;
		  cb.reason    = cbValueChange;
		  cb.cb_rtn    = variable_cb_1;

		  info->dmp_next = 0;
		  info->next  = vcd_list;
		  vcd_list    = info;

		  info->cb    = vpi_register_cb(&cb);
	    }

	    break;

	  case vpiModule:
	  case vpiGenScope:
	  case vpiFunction:
	  case vpiTask:
	  case vpiNamedBegin:
	  case vpiNamedFork:

	    if (depth > 0) {
		  char *instname;
		  char *defname = NULL;
		  /* list of types to iterate upon */
		  static int types[] = {
			/* Value */
			vpiNamedEvent,
			vpiNet,
			/* vpiParameter, */
			vpiReg,
			vpiVariables,
			/* Scope */
			vpiFunction,
			vpiGenScope,
			vpiModule,
			vpiNamedBegin,
			vpiNamedFork,
			vpiTask,
			-1
		  };
		  int i;
		  int nskip = (vcd_names_search(&fst_tab, fullname) != 0);

		    /* We have to always scan the scope because the
		     * depth could be different for this call. */
		  if (nskip) {
			vpi_printf("FST warning: ignoring signals in "
			           "previously scanned scope %s.\n", fullname);
		  } else {
			vcd_names_add(&fst_tab, fullname);
		  }

		    /* Set the file and line information for this scope.
		     * Everything has instance information. Only a module
		     * has separate definition information. */
		  instname = vpi_get_str(vpiFile, item);
		  fstWriterSetSourceInstantiationStem(dump_file, instname,
		      (int)vpi_get(vpiLineNo, item), 0);
		  if (item_type == vpiModule) {
			fstWriterSetSourceStem(dump_file,
			    vpi_get_str(vpiDefFile, item),
			    (int)vpi_get(vpiDefLineNo, item), 0);
		  } else {
			fstWriterSetSourceStem(dump_file, instname,
			    (int)vpi_get(vpiLineNo, item), 0);
		  }

		    /* This must be done before the other name is fetched
		     * and the string must always be freed */
		  if (item_type == vpiModule) {
			defname = strdup(vpi_get_str(vpiDefName, item));
		  }
		  name = vpi_get_str(vpiName, item);
		    /* If the two names match only use the vpiName. */
		  if (defname && (strcmp(defname, name) == 0)) {
			free(defname);
			defname = NULL;
		  }
		  fstWriterSetScope(dump_file, stype, name, defname);
		  free(defname);

		  for (i=0; types[i]>0; i++) {
			vpiHandle hand;
			vpiHandle argv = vpi_iterate(types[i], item);
			while (argv && (hand = vpi_scan(argv))) {
			      scan_item(depth-1, hand, nskip);
			}
		  }

		    /* Sort any signals that we added above. */
		  fstWriterSetUpscope(dump_file);
	    }
	    break;
      }
}
예제 #9
0
파일: sys_fileio.c 프로젝트: AmkG/iverilog
static PLI_INT32 sys_fread_calltf(PLI_BYTE8*name)
{
      vpiHandle callh = vpi_handle(vpiSysTfCall, 0);
      vpiHandle argv = vpi_iterate(vpiArgument, callh);
      vpiHandle arg, mem_reg;
      s_vpi_value val;
      PLI_UINT32 fd_mcd;
      PLI_INT32 start, count, width, rtn;
      unsigned is_mem, bpe, words;
      FILE *fp;
      s_vpi_vecval *vector;
      errno = 0;

	/* Get the register/memory. */
      mem_reg = vpi_scan(argv);

	/* Get the file descriptor. */
      arg = vpi_scan(argv);
      val.format = vpiIntVal;
      vpi_get_value(arg, &val);
      fd_mcd = val.value.integer;

	/* Return 0 if this is not a valid fd. */
      fp = vpi_get_file(fd_mcd);
      if (!fp) {
	    vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh),
	               (int)vpi_get(vpiLineNo, callh));
	    vpi_printf("invalid file descriptor (0x%x) given to %s.\n",
	               (unsigned int)fd_mcd, name);
	    errno = EBADF;
	    val.format = vpiIntVal;
	    val.value.integer = 0;
	    vpi_put_value(callh, &val, 0, vpiNoDelay);
	    vpi_free_object(argv);
	    return 0;
      }

	/* Are we reading into a memory? */
      if (vpi_get(vpiType, mem_reg) == vpiReg) is_mem = 0;
      else is_mem = 1;

	/* We only need to get these for memories. */
      if (is_mem) {
	    PLI_INT32 left, right, max, min;

	      /* Get the left and right memory address. */
	    val.format = vpiIntVal;
	    vpi_get_value(vpi_handle(vpiLeftRange, mem_reg), &val);
	    left = val.value.integer;
	    val.format = vpiIntVal;
	    vpi_get_value(vpi_handle(vpiRightRange, mem_reg), &val);
	    right = val.value.integer;
	    max = (left > right) ? left : right;
	    min = (left < right) ? left : right;

	      /* Get the starting address (optional). */
	    arg = vpi_scan(argv);
	    if (arg) {
		  val.format = vpiIntVal;
		  vpi_get_value(arg, &val);
		  start = val.value.integer;
		  if (start < min || start > max) {
			vpi_printf("WARNING: %s:%d: ",
			           vpi_get_str(vpiFile, callh),
			           (int)vpi_get(vpiLineNo, callh));
			vpi_printf("%s's start argument (%d) is outside "
			           "memory range [%d:%d].\n", name, (int)start,
			           (int)left, (int)right);
			val.format = vpiIntVal;
			val.value.integer = 0;
			vpi_put_value(callh, &val, 0, vpiNoDelay);
			vpi_free_object(argv);
			return 0;
		  }

		    /* Get the count (optional). */
		  arg = vpi_scan(argv);
		  if (arg) {
			val.format = vpiIntVal;
			vpi_get_value(arg, &val);
			count = val.value.integer;
			if (count > max-start) {
			      vpi_printf("WARNING: %s:%d: ",
			                 vpi_get_str(vpiFile, callh),
			                 (int)vpi_get(vpiLineNo, callh));
			      vpi_printf("%s's count argument (%d) is too "
			                 "large for start (%d) and memory "
			                 "range [%d:%d].\n", name, (int)count,
			                 (int)start, (int)left, (int)right);
			      count = max - start + 1;
			}
			vpi_free_object(argv);
		  } else {
			count = max - start + 1;
		  }
	    } else {
		  start = min;
		  count = max - min + 1;
	    }
            width = vpi_get(vpiSize, vpi_handle_by_index(mem_reg, start));
      } else {
	    start = 0;
	    count = 1;
            width = vpi_get(vpiSize, mem_reg);
	    vpi_free_object(argv);
      }

      words = (width+31)/32;
      vector = calloc(words, sizeof(s_vpi_vecval));
      bpe = (width+7)/8;

      if (is_mem) {
	    unsigned idx;
	    rtn = 0;
	    for (idx = 0; idx < count; idx += 1) {
		  vpiHandle word;
		  word = vpi_handle_by_index(mem_reg, start+(signed)idx);
		  rtn += fread_word(fp, word, words, bpe, vector);
		  if (feof(fp)) break;
	    }
      } else {
	    rtn = fread_word(fp, mem_reg, words, bpe, vector);
      }
      free(vector);

	/* Return the number of bytes read. */
      val.format = vpiIntVal;
      val.value.integer = rtn;
      vpi_put_value(callh, &val, 0, vpiNoDelay);

      return 0;
}
예제 #10
0
static void scan_item(unsigned depth, vpiHandle item, int skip)
{
      struct t_cb_data cb;
      struct vcd_info* info;

      const char *type;
      const char *name;
      const char *fullname;
      const char *prefix;
      const char *ident;
      int nexus_id;
      unsigned size;
      PLI_INT32 item_type;

	/* Get the displayed type for the various $var and $scope types. */
	/* Not all of these are supported now, but they should be in a
	 * future development version. */
      item_type = vpi_get(vpiType, item);
      switch (item_type) {
	  case vpiNamedEvent: type = "event"; break;
	  case vpiIntVar:
	  case vpiIntegerVar: type = "integer"; break;
	  case vpiParameter:  type = "parameter"; break;
	    /* Icarus converts realtime to real. */
	  case vpiRealVar:    type = "real"; break;
	  case vpiMemoryWord:
	  case vpiBitVar:
	  case vpiByteVar:
	  case vpiShortIntVar:
	  case vpiLongIntVar:
	  case vpiReg:        type = "reg"; break;
	    /* Icarus converts a time to a plain register. */
	  case vpiTimeVar:    type = "time"; break;
	  case vpiNet:
	    switch (vpi_get(vpiNetType, item)) {
		case vpiWand:    type = "wand"; break;
		case vpiWor:     type = "wor"; break;
		case vpiTri:     type = "tri"; break;
		case vpiTri0:    type = "tri0"; break;
		case vpiTri1:    type = "tri1"; break;
		case vpiTriReg:  type = "trireg"; break;
		case vpiTriAnd:  type = "triand"; break;
		case vpiTriOr:   type = "trior"; break;
		case vpiSupply1: type = "supply1"; break;
		case vpiSupply0: type = "supply0"; break;
		default:         type = "wire"; break;
	    }
	    break;

	  case vpiNamedBegin: type = "begin"; break;
	  case vpiGenScope:   type = "begin"; break;
	  case vpiNamedFork:  type = "fork"; break;
	  case vpiFunction:   type = "function"; break;
	  case vpiModule:     type = "module"; break;
	  case vpiTask:       type = "task"; break;

	  default:
	    vpi_printf("VCD warning: $dumpvars: Unsupported argument "
	               "type (%s)\n", vpi_get_str(vpiType, item));
	    return;
      }

	/* Do some special processing/checking on array words. Dumping
	 * array words is an Icarus extension. */
      if (item_type == vpiMemoryWord) {
	      /* Turn a non-constant array word select into a constant
	       * word select. */
	    if (vpi_get(vpiConstantSelect, item) == 0) {
		  vpiHandle array = vpi_handle(vpiParent, item);
		  PLI_INT32 idx = vpi_get(vpiIndex, item);
		  item = vpi_handle_by_index(array, idx);
	    }

	      /* An array word is implicitly escaped so look for an
	       * escaped identifier that this could conflict with. */
	      /* This does not work as expected since we always find at
	       * least the array word. We likely need a custom routine. */
            if (vpi_get(vpiType, item) == vpiMemoryWord &&
                vpi_handle_by_name(vpi_get_str(vpiFullName, item), 0)) {
		  vpi_printf("VCD warning: array word %s will conflict "
		             "with an escaped identifier.\n",
		             vpi_get_str(vpiFullName, item));
            }
      }

      fullname = vpi_get_str(vpiFullName, item);

	/* Generate the $var or $scope commands. */
      switch (item_type) {
	  case vpiParameter:
	    vpi_printf("VCD sorry: $dumpvars: can not dump parameters.\n");
	    break;

	  case vpiNamedEvent:
	  case vpiIntegerVar:
	  case vpiBitVar:
	  case vpiByteVar:
	  case vpiShortIntVar:
	  case vpiIntVar:
	  case vpiLongIntVar:
	  case vpiRealVar:
	  case vpiMemoryWord:
	  case vpiReg:
	  case vpiTimeVar:
	  case vpiNet:


	      /* If we are skipping all signal or this is in an automatic
	       * scope then just return. */
            if (skip || vpi_get(vpiAutomatic, item)) return;

	      /* Skip this signal if it has already been included.
	       * This can only happen for implicitly given signals. */
	    if (vcd_names_search(&vcd_var, fullname)) return;

	      /* Declare the variable in the VCD file. */
	    name = vpi_get_str(vpiName, item);
	    prefix = is_escaped_id(name) ? "\\" : "";

	      /* Some signals can have an alias so handle that. */
	    nexus_id = vpi_get(_vpiNexusId, item);

	    ident = 0;
	    if (nexus_id) ident = find_nexus_ident(nexus_id);

	    if (!ident) {
		  ident = strdup(vcdid);
		  gen_new_vcd_id();

		  if (nexus_id) set_nexus_ident(nexus_id, ident);

		    /* Add a callback for the signal. */
		  info = malloc(sizeof(*info));

		  info->time.type = vpiSimTime;
		  info->item  = item;
		  info->ident = ident;
		  info->scheduled = 0;

		  cb.time      = &info->time;
		  cb.user_data = (char*)info;
		  cb.value     = NULL;
		  cb.obj       = item;
		  cb.reason    = cbValueChange;
		  cb.cb_rtn    = variable_cb_1;

		  info->dmp_next = 0;
		  info->next  = vcd_list;
		  vcd_list    = info;

		  info->cb    = vpi_register_cb(&cb);
	    }

	      /* Named events do not have a size, but other tools use
	       * a size of 1 and some viewers do not accept a width of
	       * zero so we will also use a width of one for events. */
	    if (item_type == vpiNamedEvent) size = 1;
	    else size = vpi_get(vpiSize, item);

	    fprintf(dump_file, "$var %s %u %s %s%s",
		    type, size, ident, prefix, name);

	      /* Add a range for vectored values. */
	    if (size > 1 || vpi_get(vpiLeftRange, item) != 0) {
		  fprintf(dump_file, " [%i:%i]",
			  (int)vpi_get(vpiLeftRange, item),
			  (int)vpi_get(vpiRightRange, item));
	    }

	    fprintf(dump_file, " $end\n");
	    break;

	  case vpiModule:
	  case vpiGenScope:
	  case vpiFunction:
	  case vpiTask:
	  case vpiNamedBegin:
	  case vpiNamedFork:

	    if (depth > 0) {
		/* list of types to iterate upon */
		  static int types[] = {
			/* Value */
			vpiNamedEvent,
			vpiNet,
			/* vpiParameter, */
			vpiReg,
			vpiVariables,
			/* Scope */
			vpiFunction,
			vpiGenScope,
			vpiModule,
			vpiNamedBegin,
			vpiNamedFork,
			vpiTask,
			-1
		  };
		  int i;
		  int nskip = (vcd_names_search(&vcd_tab, fullname) != 0);

		    /* We have to always scan the scope because the
		     * depth could be different for this call. */
		  if (nskip) {
			vpi_printf("VCD warning: ignoring signals in "
			           "previously scanned scope %s.\n", fullname);
		  } else {
			vcd_names_add(&vcd_tab, fullname);
		  }

		  name = vpi_get_str(vpiName, item);
		  fprintf(dump_file, "$scope %s %s $end\n", type, name);

		  for (i=0; types[i]>0; i++) {
			vpiHandle hand;
			vpiHandle argv = vpi_iterate(types[i], item);
			while (argv && (hand = vpi_scan(argv))) {
			      scan_item(depth-1, hand, nskip);
			}
		  }

		    /* Sort any signals that we added above. */
		  fprintf(dump_file, "$upscope $end\n");
	    }
	    break;
      }
}