diff --git a/vpi/sys_readmem.c b/vpi/sys_readmem.c index d20723dd9..7c28c7ed5 100644 --- a/vpi/sys_readmem.c +++ b/vpi/sys_readmem.c @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: sys_readmem.c,v 1.8 2001/12/01 02:40:10 steve Exp $" +#ident "$Id: sys_readmem.c,v 1.9 2002/01/31 04:28:17 steve Exp $" #endif # include "config.h" @@ -29,11 +29,45 @@ # include # include "sys_readmem_lex.h" +static int check_integer_constant(char*name, vpiHandle handle) +{ + if (vpi_get(vpiType, handle) != vpiConstant){ + vpi_printf("ERROR: %s parameter must be a constant\n", name); + return 0; + } + + switch(vpi_get(vpiConstType, handle)){ + case vpiDecConst: + case vpiBinaryConst: + case vpiOctConst: + case vpiHexConst: + return 1; + break; + + /* We rely on vpi_get_value for reals and strings to return a correct */ + /* integer value when this is requested. So only a warning is generated. */ + case vpiRealConst: + vpi_printf("Warning: real supplied to %s instead of integer.\n", name); + return 1; + break; + + case vpiStringConst: + vpi_printf("Warning: string supplied to %s instead of integer.\n", name); + return 1; + break; + } + + /* switch statement covers all possibilities. Code should never come here... */ + assert(0); + return 0; +} + static int sys_readmem_calltf(char*name) { int code; int wwid; char*path; + char*mem_name; FILE*file; unsigned addr; s_vpi_value value; @@ -42,6 +76,28 @@ static int sys_readmem_calltf(char*name) 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 right_addr) { + vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name); + return 0; + } + + if (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 left_addr) { + vpi_printf("%s: Start address is out of bounds for memory \'%s\'!\n", name, mem_name); + return 0; + } + + if (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); + /* 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)); + 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); - addr = 0; + /*======================================== 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: - if (addr > value.value.vector->aval) { - vpi_free_object(words); - words = vpi_iterate(vpiMemoryWord, mitem); - item = vpi_scan(words); - addr = 0; - } - while (item && addr < value.value.vector->aval) { - item = vpi_scan(words); - addr += 1; - } - break; - case MEM_WORD: - if (item) { - vpi_put_value(item, &value, 0, vpiNoDelay); - item = vpi_scan(words); - addr += 1; - } else { - vpi_printf("%s(%s): too much data (addr=0x%x)\n", - name, path, addr); - goto bailout; - } - break; - default: - vpi_printf("Huh?! (%d)\n", code); - break; - } + switch (code) { + case MEM_ADDRESS: + addr = value.value.vector->aval; + 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); + } + 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; + } } - bailout: - if (item) vpi_free_object(words); - free(path); + bailout: free(value.value.vector); + + if (item) + vpi_free_object(words); + free(path); fclose(file); return 0; } @@ -177,7 +335,7 @@ static int sys_writemem_calltf(char*name) vpi_get_value(item, &value); path = strdup(value.value.str); - /* Get and check the second paramter. It must be a memory. */ + /* Get and check the second parameter. It must be a memory. */ item = vpi_scan(argv); if (item == 0) { vpi_printf("%s: Missing memory parameter\n", name); @@ -253,6 +411,9 @@ void sys_readmem_register() /* * $Log: sys_readmem.c,v $ + * Revision 1.9 2002/01/31 04:28:17 steve + * Full support for $readmem ranges (Tom Verbeure) + * * Revision 1.8 2001/12/01 02:40:10 steve * Support addresses in readmemh. * diff --git a/vvp/memory.cc b/vvp/memory.cc index 7c7e0498a..032742248 100644 --- a/vvp/memory.cc +++ b/vvp/memory.cc @@ -18,7 +18,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: memory.cc,v 1.14 2001/12/06 03:31:24 steve Exp $" +#ident "$Id: memory.cc,v 1.15 2002/01/31 04:28:17 steve Exp $" #endif #include "memory.h" @@ -63,6 +63,10 @@ struct vvp_memory_index_s { int first; // first memory address unsigned size; // number of valid addresses + + // Added to correctly support vpiLeftRange and vpiRightRange + int left; + int right; }; struct vvp_memory_port_s : public functor_s @@ -95,6 +99,30 @@ unsigned memory_root(vvp_memory_t mem, unsigned ix) return mem->a_idx[ix].first; } +unsigned memory_left_range(vvp_memory_t mem, unsigned ix) +{ + if (ix >= mem->a_idxs) + return 0; + return mem->a_idx[ix].left; +} + +unsigned memory_right_range(vvp_memory_t mem, unsigned ix) +{ + if (ix >= mem->a_idxs) + return 0; + return mem->a_idx[ix].right; +} + +unsigned memory_word_left_range(vvp_memory_t mem) +{ + return mem->msb; +} + +unsigned memory_word_right_range(vvp_memory_t mem) +{ + return mem->lsb; +} + char *memory_name(vvp_memory_t mem) { return mem->name; @@ -146,6 +174,10 @@ void memory_new(vvp_memory_t mem, char *name, int msb, int lsb, vvp_memory_index_t x = mem->a_idx + i; int msw = *(idx++); int lsw = *(idx++); + + x->left = msw; + x->right = lsw; + if (msw > lsw) { x->size = msw - lsw + 1; x->first = lsw; diff --git a/vvp/memory.h b/vvp/memory.h index c91b9917e..a109b923d 100644 --- a/vvp/memory.h +++ b/vvp/memory.h @@ -20,7 +20,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: memory.h,v 1.4 2001/10/31 04:27:47 steve Exp $" +#ident "$Id: memory.h,v 1.5 2002/01/31 04:28:17 steve Exp $" #endif #include "pointers.h" @@ -52,6 +52,10 @@ unsigned memory_size(vvp_memory_t mem); char *memory_name(vvp_memory_t mem); unsigned memory_data_width(vvp_memory_t mem); unsigned memory_root(vvp_memory_t mem, unsigned ix = 0); +unsigned memory_left_range(vvp_memory_t mem, unsigned ix = 0); +unsigned memory_right_range(vvp_memory_t mem, unsigned ix = 0); +unsigned memory_word_left_range(vvp_memory_t mem); +unsigned memory_word_right_range(vvp_memory_t mem); /* ** Access to the memory symbol table. @@ -61,6 +65,9 @@ vvp_memory_t memory_create(char *label); /* * $Log: memory.h,v $ + * Revision 1.5 2002/01/31 04:28:17 steve + * Full support for $readmem ranges (Tom Verbeure) + * * Revision 1.4 2001/10/31 04:27:47 steve * Rewrite the functor type to have fewer functor modes, * and use objects to manage the different types. diff --git a/vvp/vpi_const.cc b/vvp/vpi_const.cc index 3dc283c1f..f414c2dfc 100644 --- a/vvp/vpi_const.cc +++ b/vvp/vpi_const.cc @@ -17,7 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vpi_const.cc,v 1.9 2002/01/25 03:24:19 steve Exp $" +#ident "$Id: vpi_const.cc,v 1.10 2002/01/31 04:28:17 steve Exp $" #endif # include "vpi_priv.h" @@ -336,10 +336,110 @@ vpiHandle vpip_make_binary_const(unsigned wid, char*bits) } + +static int dec_get(int code, vpiHandle ref) +{ + + switch (code) { + case vpiConstType: + return vpiDecConst; + + case vpiSigned: + return 1; + + case vpiSize: + return 32; + + default: + fprintf(stderr, "vvp error: get %d not supported " + "by vpiDecConst\n", code); + assert(0); + return 0; + } +} + + +static void dec_value(vpiHandle ref, p_vpi_value vp) +{ + struct __vpiDecConst*rfp = (struct __vpiDecConst*)ref; + char* cp; + assert(ref->vpi_type->type_code == vpiConstant); + + switch (vp->format) { + + case vpiObjTypeVal: + case vpiIntVal: { + vp->value.integer = rfp->value; + break; + } + + case vpiDecStrVal: + sprintf(buf, "%d", rfp->value); + + vp->format = vpiDecStrVal; + vp->value.str = buf; + break; + + case vpiBinStrVal: + cp = buf; + for(int bit=31; bit<=0;bit--){ + *cp++ = "01"[ (rfp->value>>bit)&1 ]; + } + *cp = 0; + + vp->format = vpiBinStrVal; + vp->value.str = buf; + break; + + case vpiHexStrVal: + sprintf(buf, "%08x", rfp->value); + + vp->format = vpiHexStrVal; + vp->value.str = buf; + break; + + case vpiOctStrVal: + sprintf(buf, "%011x", rfp->value); + + vp->format = vpiOctStrVal; + vp->value.str = buf; + break; + + default: + fprintf(stderr, "vvp error (vpi_const.cc): format %d not supported " + "by vpiDecConst\n", vp->format); + vp->format = vpiSuppressVal; + break; + } +} + +static const struct __vpirt vpip_dec_rt = { + vpiConstant, + dec_get, + 0, + dec_value, + 0, + 0, + 0 +}; + +vpiHandle vpip_make_dec_const(int value) +{ + struct __vpiDecConst*obj; + + obj = (struct __vpiDecConst*) + malloc(sizeof (struct __vpiDecConst)); + obj->base.vpi_type = &vpip_dec_rt; + obj->value = value; + + return &(obj->base); +} + + /* * $Log: vpi_const.cc,v $ - * Revision 1.9 2002/01/25 03:24:19 steve - * Support display of strings with umber formats. (Tom Verbeure) + * Revision 1.10 2002/01/31 04:28:17 steve + * Full support for $readmem ranges (Tom Verbeure) * * Revision 1.8 2002/01/15 03:21:18 steve * Support DesSTrVal for binary constants. diff --git a/vvp/vpi_memory.cc b/vvp/vpi_memory.cc index 2ca7ccd3f..e5ad040c5 100644 --- a/vvp/vpi_memory.cc +++ b/vvp/vpi_memory.cc @@ -27,7 +27,7 @@ * Picture Elements, Inc., 777 Panoramic Way, Berkeley, CA 94704. */ #if !defined(WINNT) && !defined(macintosh) -#ident "$Id: vpi_memory.cc,v 1.3 2001/12/07 23:23:05 steve Exp $" +#ident "$Id: vpi_memory.cc,v 1.4 2002/01/31 04:28:17 steve Exp $" #endif # include "vpi_priv.h" @@ -40,6 +40,8 @@ struct __vpiMemoryWord { struct __vpiHandle base; struct __vpiMemory*mem; int index; + struct __vpiDecConst*left_range; + struct __vpiDecConst*right_range; }; struct __vpiMemory { @@ -47,8 +49,28 @@ struct __vpiMemory { /* The signal has a name (this points to static memory.) */ struct __vpiMemoryWord word; vvp_memory_t mem; + struct __vpiDecConst*left_range; + struct __vpiDecConst*right_range; + }; +static vpiHandle memory_get_handle(int code, vpiHandle obj) +{ + struct __vpiMemory*rfp = (struct __vpiMemory*)obj; + + assert(obj->vpi_type->type_code==vpiMemory); + + switch(code){ + case vpiLeftRange: + return &(rfp->left_range->base); + + case vpiRightRange: + return &(rfp->right_range->base); + } + + return 0; +} + static int vpi_memory_get(int code, vpiHandle ref) { struct __vpiMemory*rfp = (struct __vpiMemory*)ref; @@ -139,6 +161,25 @@ static vpiHandle memory_index(vpiHandle ref, int index) return &rfp->word.base; } +//============================== + +static vpiHandle memory_word_get_handle(int code, vpiHandle obj) +{ + struct __vpiMemoryWord*rfp = (struct __vpiMemoryWord*)obj; + + assert(obj->vpi_type->type_code==vpiMemoryWord); + + switch(code){ + case vpiLeftRange: + return &(rfp->left_range->base); + + case vpiRightRange: + return &(rfp->right_range->base); + } + + return 0; +} + static int memory_word_get(int code, vpiHandle ref) { struct __vpiMemoryWord*rfp = (struct __vpiMemoryWord*)ref; @@ -234,7 +275,7 @@ static const struct __vpirt vpip_memory_rt = { memory_get_str, 0, 0, - 0, + memory_get_handle, memory_iterate, memory_index, }; @@ -245,7 +286,7 @@ static const struct __vpirt vpip_memory_word_rt = { 0, memory_word_get_value, memory_word_put, - 0, + memory_word_get_handle, 0, 0, }; @@ -256,15 +297,23 @@ vpiHandle vpip_make_memory(vvp_memory_t mem) malloc(sizeof(struct __vpiMemory)); obj->base.vpi_type = &vpip_memory_rt; - obj->word.base.vpi_type = &vpip_memory_word_rt; obj->mem = mem; + obj->left_range = (struct __vpiDecConst*)vpip_make_dec_const(memory_left_range(mem)); + obj->right_range = (struct __vpiDecConst*)vpip_make_dec_const(memory_right_range(mem)); + + obj->word.base.vpi_type = &vpip_memory_word_rt; obj->word.mem = obj; + obj->word.left_range = (struct __vpiDecConst*)vpip_make_dec_const(memory_word_left_range(mem)); + obj->word.right_range = (struct __vpiDecConst*)vpip_make_dec_const(memory_word_right_range(mem)); return &(obj->base); } /* * $Log: vpi_memory.cc,v $ + * Revision 1.4 2002/01/31 04:28:17 steve + * Full support for $readmem ranges (Tom Verbeure) + * * Revision 1.3 2001/12/07 23:23:05 steve * vpi_put_value of vpiIntVal for memory words. * diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 1d41aa654..bf146bad2 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -19,7 +19,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ #if !defined(WINNT) -#ident "$Id: vpi_priv.h,v 1.26 2002/01/06 17:50:50 steve Exp $" +#ident "$Id: vpi_priv.h,v 1.27 2002/01/31 04:28:17 steve Exp $" #endif # include "vpi_user.h" @@ -183,6 +183,13 @@ struct __vpiBinaryConst { vpiHandle vpip_make_binary_const(unsigned wid, char*bits); +struct __vpiDecConst { + struct __vpiHandle base; + int value; +}; + +vpiHandle vpip_make_dec_const(int value); + /* * This one looks like a constant, but really is a vector in the current * thread. @@ -250,6 +257,9 @@ extern void functor_set_scope(vpiHandle scope); /* * $Log: vpi_priv.h,v $ + * Revision 1.27 2002/01/31 04:28:17 steve + * Full support for $readmem ranges (Tom Verbeure) + * * Revision 1.26 2002/01/06 17:50:50 steve * Support scope for functors. (Stephan Boettcher) *