Compare commits

..
28 Commits
Author SHA1 Message Date
Stephen Williams 0fecdcbeda Icarus Verilog snapshot 2015-01-05 2015-01-05 10:34:18 -08:00
Cary R 23ad62f317 Update cppcheck results 2014-12-28 09:27:14 -08:00
Cary R ac20008606 Update lz4 files from GTKWave 2014-12-28 09:25:54 -08:00
Stephen Williams 96d181efed Support vpiStrengthVal for vec4 stack objects. 2014-12-23 14:42:45 -08:00
Stephen Williams 18bfe7d497 Merge branch 'master' of github.com:steveicarus/iverilog 2014-12-23 13:52:48 -08:00
Stephen Williams 86562e60ba Work towards nested packed struct member vectors. 2014-12-23 13:52:38 -08:00
Martin Whitaker b400532169 Added support for interface declaration and instantiation.
modport and extern tf declarations are not yet supported.
2014-12-19 23:10:14 +00:00
Stephen Williams 6fd10dedb6 Add some implicit support for std and textio libraries
Patch submitted by Fabrizio Ferrandi.
2014-12-18 08:20:19 -08:00
Cary R c8255952a3 Update cppcheck supprression file 2014-12-16 16:47:00 -08:00
Martin Whitaker 71c4ea36e8 Pass -v compiler option to vvp in the output file shebang line.
Slightly modified version of the patch contributed by Stephan
Böttcheron iverilog-devel.
2014-12-16 21:22:19 +00:00
Martin Whitaker 5df179cd5f Implement feature request #47.
This causes vvp to evaluate all the input expressions for a user
function call before assigning any of them to the function input
variables. This stops the input variables being overwritten if
the same (non-automatic) function is used in one of the input
expressions.
2014-12-14 21:46:28 +00:00
Martin Whitaker ce5c4ca8ba Fix for br967 - allow real value for repeat statement loop length. 2014-12-13 19:50:33 +00:00
Martin Whitaker 6aa8e49b09 Add sorry message for unsupported arrays of named events. 2014-12-13 17:46:56 +00:00
Martin Whitaker f29f4ff4e3 Fix for br965.
When performing constant propagation, we need to take into account
values driven through a tran object. For now, be pessimistic, and
assume that all tran objects connect to a variable driver.
2014-12-13 12:49:13 +00:00
Cary R 3ccc59eaa3 Fix compile with valgrind hooks after vec4-stack changes 2014-12-12 14:28:07 -08:00
Martin Whitaker 0282b8450c Fix potential memory leak when a thread is disabled.
A disable statement can terminate a thread whilst it still has
local variables on the stack (e.g. the loop counter for a repeat
statement). We need to clear the thread stacks when this happens.
2014-12-11 20:10:17 +00:00
Cary R 43841af2f3 Fix a cppcheck warning and fix code style a bit 2014-12-11 09:59:15 -08:00
Cary R b2d8d41e3f Fix some cppcheck warnings in tgt-vvp 2014-12-10 16:30:55 -08:00
Cary R 0e38843ae9 Make verinum output match for either 32-bit or 64-bit systems 2014-12-10 15:11:45 -08:00
Cary R 96472e5537 For a signed R-value we can use the full width when converting to long
When trying to get the value we can use the full width of a long if the
expression is signed.
2014-12-10 14:41:27 -08:00
Cary R 48b0fed29e Use uint64_t casting of constants since UL does not work on 32-bit machines
Using a UL constant in a unit64_t context does not work on a 32-bit
machine since UL is 32-bits. Instead create uint64_t constants using
static casts and the appropriate bit operators.
2014-12-10 14:41:18 -08:00
Cary R 1efa220773 Fix non-blocking assignment to an array error state handling
If either the index or part offset expressions generate an undefined
value then the assignment is skipped. This patch reworks the code that
handles the flags used to detect this. For some simple cases a global
flag is not needed, but for other cases one is needed since there are
two expressions that can generate an error and even when there is only
a variable expression this error state needs to be preserved if there
is a variable delay. An undefined delay value defaults to zero and is
not an error.
2014-12-09 17:29:18 -08:00
Cary R 2d6622e543 vlog95: for a 32-bit width we can generate a signed undefined value 2014-12-08 21:09:36 -08:00
Cary R edf112b900 Update all the vvp examples to work correctly 2014-12-08 20:55:19 -08:00
Cary R f0a0ab100f vlog95: trim binary constants to save space and emit size of undef. consts.
This should not change the functionality, but to save space trim any
unneeded bits from a binary constant. Also for the case of emitting
a signed undefined value when the allow signed flag is not set add
the width to the constant.
2014-12-08 13:08:30 -08:00
Cary R c28188618b File example vvp code so make check passes. 2014-12-08 10:43:46 -08:00
Martin Whitaker 0d7daf5862 Fix vvp memory leak for user function calls in a continuous assignment. 2014-12-07 13:47:50 +00:00
Martin Whitaker 60ab1daa1f Restore some master branch fixes lost in the vec4-stack merge. 2014-12-07 12:10:15 +00:00
47 changed files with 1500 additions and 1176 deletions
+9
View File
@@ -47,6 +47,10 @@ class NetScope;
* A module is a named container and scope. A module holds a bunch of
* semantic quantities such as wires and gates. The module is
* therefore the handle for grasping the described circuit.
*
* SystemVerilog introduces program blocks and interfaces. These have
* much in common with modules, so the Module class is used to represent
* these containers as well.
*/
class Module : public PScopeExtra, public LineInfo {
@@ -81,6 +85,11 @@ class Module : public PScopeExtra, public LineInfo {
restrictions and slightly modify scheduling semantics. */
bool program_block;
/* This is true if the module represents a interface
instead of a module/cell. Interfaces have different
content restrictions and some extra allowed items. */
bool is_interface;
enum UCDriveType { UCD_NONE, UCD_PULL0, UCD_PULL1 };
UCDriveType uc_drive;
+2 -2
View File
@@ -1,3 +1,3 @@
// These are correct and are used to find the base (zero) pin.
thisSubtraction:netlist.h:4938
thisSubtraction:netlist.h:4947
thisSubtraction:netlist.h:4971
thisSubtraction:netlist.h:4980
+1
View File
@@ -1375,6 +1375,7 @@ void NetScope::dump(ostream&o) const
if (is_cell()) o << " (cell)";
if (nested_module()) o << " (nested)";
if (program_block()) o << " (program)";
if (is_interface()) o << " (interface)";
o << " " << children_.size() << " children, "
<< classes_.size() << " classes" << endl;
+7 -1
View File
@@ -1,4 +1,4 @@
.TH iverilog 1 "February 26th, 2014" "" "Version %M.%m.%n %E"
.TH iverilog 1 "December 16th, 2014" "" "Version %M.%m.%n %E"
.SH NAME
iverilog - Icarus Verilog compiler
@@ -213,6 +213,12 @@ a reference to a key temporary file that passes information to the
compiler proper. To keep that file from being deleted at the end
of the process, provide a file name of your own in the environment
variable \fBIVERILOG_ICONFIG\fP.
If the selected target is \fIvvp\fP, the \fB\-v\fP switch is appended
to the shebang line in the compiler output file, so directly executing
the compiler output file will turn on verbose messages in \fIvvp\fP.
This extra verbosity can be avoided by using the \fIvvp\fP command to
indirectly execute the compiler output file.
.TP 8
.B -V
Print the version of the compiler, and exit.
+5 -2
View File
@@ -785,8 +785,11 @@ unsigned PEBLeftWidth::test_width(Design*des, NetScope*scope, width_mode_t&mode)
right_ = tmp;
}
NetEConst*rc = dynamic_cast<NetEConst*> (rp);
if (rc && (r_width < sizeof(long)*8))
r_val = rc->value().as_long();
// Adjust the expression width that can be converter depending
// on if the R-value is signed or not.
unsigned c_width = sizeof(long)*8;
if (! right_->has_sign()) c_width -= 1;
if (rc && (r_width <= c_width)) r_val = rc->value().as_long();
if (debug_elaborate && rc) {
cerr << get_fileline() << ": PEBLeftWidth::test_width: "
+5 -4
View File
@@ -157,7 +157,7 @@ NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
return 0;
pform_name_t use_path = cur_path;
perm_string tmp_name = peek_tail_name(use_path);
name_component_t tail = use_path.back();
use_path.pop_back();
NetNet* reg = 0;
@@ -171,18 +171,19 @@ NetAssign_*PEIdent::scan_lname_for_nested_members_(Design*des, NetScope*scope,
return 0;
tmp = new NetAssign_(tmp);
tmp->set_property(tmp_name);
tmp->set_property(tail.name);
return tmp;
}
if (reg->struct_type()) {
cerr << get_fileline() << ": sorry: "
<< "I don't know what to do with struct " << use_path << endl;
<< "I don't know what to do with struct " << use_path
<< " with member " << tail << "." << endl;
return 0;
}
if (reg->class_type()) {
return elaborate_lval_net_class_member_(des, scope, reg, tmp_name);
return elaborate_lval_net_class_member_(des, scope, reg, tail.name);
}
return 0;
+9 -22
View File
@@ -201,16 +201,15 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
verinum one_value ((uint64_t)1, enum_width);
one_value.has_sign(enum_type->signed_flag);
// Find the maximum allowed enumeration value.
verinum min_value (0);
verinum max_value (0);
if (enum_type->signed_flag) {
min_value = -pow(verinum(2), verinum(enum_width-1));
max_value = pow(verinum(2), verinum(enum_width-1)) - one_value;
} else {
max_value = pow(verinum(2), verinum(enum_width)) - one_value;
}
min_value.has_sign(true);
max_value.has_sign(enum_type->signed_flag);
// Variable to indicate when a defined value wraps.
bool implicit_wrapped = false;
// Process the enumeration definition.
for (list<named_pexpr_t>::const_iterator cur = enum_type->names->begin()
; cur != enum_type->names->end() ; ++ cur, name_idx += 1) {
@@ -229,6 +228,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
continue;
}
cur_value = val_const->value();
// Clear the implicit wrapped flag if a parameter is given.
implicit_wrapped = false;
// A 2-state value can not have a constant with X/Z bits.
if (enum_type->base_type==IVL_VT_BOOL &&
@@ -335,24 +336,8 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
continue;
}
// Cast any undefined bits to zero so the comparisons below
// return just true (1) or false (0).
verinum two_state_value = cur_value;
two_state_value.cast_to_int2();
// The enumeration value must fit into the enumeration bits.
if (!cur_value.is_defined()) {
if (cur_value.len() > (unsigned long)use_enum->packed_width()) {
cerr << use_enum->get_fileline()
<< ": error: Enumeration name " << cur->name
<< " value=" << cur_value
<< " is too wide for enumeration base type." << endl;
des->errors += 1;
}
} else if ((two_state_value > max_value) ||
(cur_value.has_sign() && (two_state_value < min_value))) {
// Check to see if an implicitly wrapped value is used.
if (implicit_wrapped) {
cerr << use_enum->get_fileline()
<< ": error: Enumeration name " << cur->name
<< " has an inferred value that overflowed." << endl;
@@ -385,6 +370,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope,
// In case the next name has an implicit value,
// increment the current value by one.
if (cur_value.is_defined()) {
if (cur_value == max_value) implicit_wrapped = true;
cur_value = cur_value + one_value;
}
}
@@ -1756,7 +1742,8 @@ void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*s
// scope searches will continue into the parent scope.
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE,
bound_type_? true : false,
mod->program_block);
mod->program_block,
mod->is_interface);
my_scope->set_line(get_file(), mod->get_file(),
get_lineno(), mod->get_lineno());
my_scope->set_module_name(mod->mod_name());
+46 -33
View File
@@ -32,6 +32,44 @@
using namespace std;
/*
* Some types have a list of ranges that need to be elaborated. This
* function elaborates the ranges referenced by "dims" into the vector
* "ranges".
*/
static void elaborate_array_ranges(Design*des, NetScope*scope,
vector<netrange_t>&ranges,
const list<pform_range_t>*dims)
{
if (dims == 0)
return;
for (list<pform_range_t>::const_iterator cur = dims->begin()
; cur != dims->end() ; ++ cur) {
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
/* If elaboration failed for either expression, we
should have already reported the error, so just
skip the following evaluation to recover. */
long mnum = 0, lnum = 0;
if ( me && ! eval_as_long(mnum, me) ) {
assert(0);
des->errors += 1;
}
if ( le && ! eval_as_long(lnum, le) ) {
assert(0);
des->errors += 1;
}
ranges.push_back(netrange_t(mnum, lnum));
}
}
/*
* Elaborations of types may vary depending on the scope that it is
* done in, so keep a per-scope cache of the results.
@@ -120,33 +158,7 @@ ivl_type_s* enum_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
ivl_type_s* vector_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{
vector<netrange_t> packed;
if (pdims.get()) {
for (list<pform_range_t>::const_iterator cur = pdims->begin()
; cur != pdims->end() ; ++ cur) {
NetExpr*me = elab_and_eval(des, scope, cur->first, 0, true);
NetExpr*le = elab_and_eval(des, scope, cur->second, 0, true);
/* If elaboration failed for either expression, we
should have already reported the error, so just
skip the following evaluation to recover. */
long mnum = 0, lnum = 0;
if ( me && ! eval_as_long(mnum, me) ) {
assert(0);
des->errors += 1;
}
if ( le && ! eval_as_long(lnum, le) ) {
assert(0);
des->errors += 1;
}
packed.push_back(netrange_t(mnum, lnum));
}
}
elaborate_array_ranges(des, scope, packed, pdims.get());
netvector_t*tmp = new netvector_t(packed, base_type);
tmp->set_signed(signed_flag);
@@ -171,13 +183,14 @@ ivl_type_s* string_type_t::elaborate_type_raw(Design*, NetScope*) const
return &netstring_t::type_string;
}
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*) const
ivl_type_s* parray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
{
cerr << get_fileline() << " : sorry: "
<< "Packed arrays are not currently supported in this context."
<< endl;
des->errors += 1;
return 0;
vector<netrange_t>packed;
elaborate_array_ranges(des, scope, packed, dims.get());
ivl_type_t etype = base_type->elaborate_type(des, scope);
return new netparray_t(packed, etype);
}
netstruct_t* struct_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
+6 -1
View File
@@ -5013,6 +5013,10 @@ NetProc* PRepeat::elaborate(Design*des, NetScope*scope) const
des->errors += 1;
return 0;
}
// If the expression is real, convert to an integer. 64 bits
// should be more enough for any real use case.
if (expr->expr_type() == IVL_VT_REAL)
expr = cast_to_int4(expr, 64);
NetProc*stat = statement_->elaborate(des, scope);
if (stat == 0) return 0;
@@ -6086,7 +6090,8 @@ Design* elaborate(list<perm_string>roots)
// Make the root scope. This makes a NetScope object and
// pushes it into the list of root scopes in the Design.
NetScope*scope = des->make_root_scope(*root, rmod->program_block);
NetScope*scope = des->make_root_scope(*root, rmod->program_block,
rmod->is_interface);
// Collect some basic properties of this scope from the
// Module definition.
+140 -301
View File
@@ -136,21 +136,11 @@ static void ifdef_leave(void)
* we assume that the non-file part is from this file. */
if (istack->path != NULL && cur->path != NULL &&
strcmp(istack->path,cur->path) != 0) {
fprintf
(
stderr,
"%s:%u: warning: This `endif matches an ifdef in another file.\n",
istack->path,
istack->lineno+1
);
fprintf(stderr, "%s:%u: warning: This `endif matches an ifdef "
"in another file.\n", istack->path, istack->lineno+1);
fprintf
(
stderr,
"%s:%u: This is the odd matched `ifdef.\n",
cur->path,
cur->lineno+1
);
fprintf(stderr, "%s:%u: This is the odd matched `ifdef.\n",
cur->path, cur->lineno+1);
}
free(cur->path);
@@ -243,12 +233,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<PCOMENT>`{keywords} {
emit_pathline(istack);
error_count += 1;
fprintf
(
stderr,
"error: macro names cannot be directive keywords ('%s'); replaced with nothing.\n",
yytext
);
fprintf(stderr, "error: macro names cannot be directive keywords "
"('%s'); replaced with nothing.\n", yytext);
}
<PCOMENT>`[a-zA-Z][a-zA-Z0-9_$]* {
@@ -285,12 +271,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
<PPINCLUDE>`{keywords} {
emit_pathline(istack);
error_count += 1;
fprintf
(
stderr,
"error: macro names cannot be directive keywords ('%s'); replaced with nothing.\n",
yytext
);
fprintf(stderr, "error: macro names cannot be directive keywords "
"('%s'); replaced with nothing.\n", yytext);
}
<PPINCLUDE>`[a-zA-Z][a-zA-Z0-9_]* {
@@ -342,11 +324,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
emit_pathline(istack);
error_count += 1;
BEGIN(ERROR_LINE);
fprintf
(
stderr,
"error: malformed `define directive: macro names cannot be directive keywords\n"
);
fprintf(stderr, "error: malformed `define directive: macro names "
"cannot be directive keywords\n");
}
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*"("{W}? { BEGIN(DEF_ARG); def_start(); }
@@ -483,73 +462,45 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
`ifdef {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `ifdef without a macro name - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `ifdef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
}
`ifndef {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `ifndef without a macro name - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `ifndef without a macro name - ignored.\n",
istack->path, istack->lineno+1);
}
`elsif {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `elsif without a macro name - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `elsif without a macro name - ignored.\n",
istack->path, istack->lineno+1);
}
`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `elsif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `elsif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
}
`else {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `else without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `else without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
}
`endif {
error_count += 1;
fprintf
(
stderr,
"%s:%u: `endif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1
);
fprintf(stderr, "%s:%u: `endif without a matching `ifdef - ignored.\n",
istack->path, istack->lineno+1);
}
`{keywords} {
emit_pathline(istack);
error_count += 1;
fprintf
(
stderr,
"error: macro names cannot be directive keywords ('%s'); replaced with nothing.\n",
yytext
);
fprintf(stderr, "error: macro names cannot be directive keywords "
"('%s'); replaced with nothing.\n", yytext);
}
/* This pattern notices macros and arranges for them to be replaced. */
@@ -722,17 +673,14 @@ static struct define_t* magic_table = &def_LINE;
*/
static struct define_t* def_lookup_internal(const char*name, struct define_t*cur)
{
if (cur == 0)
return 0;
if (cur == 0) return 0;
assert(cur->up == 0);
while (cur)
{
while (cur) {
int cmp = strcmp(name, cur->name);
if (cmp == 0)
return cur;
if (cmp == 0) return cur;
cur = (cmp < 0) ? cur->left : cur->right;
}
@@ -743,11 +691,9 @@ static struct define_t* def_lookup_internal(const char*name, struct define_t*cur
static struct define_t* def_lookup(const char*name)
{
// first, try a magic macro
if(name[0] == '_' && name[1] == '_' && name[2] != '\0')
{
if(name[0] == '_' && name[1] == '_' && name[2] != '\0') {
struct define_t* result = def_lookup_internal(name, magic_table);
if(result)
{
if(result) {
return result;
}
}
@@ -806,8 +752,7 @@ static /* inline */ char* def_argv(int arg)
static void check_for_max_args(void)
{
if (def_argc == MAX_DEF_ARG)
{
if (def_argc == MAX_DEF_ARG) {
emit_pathline(istack);
fprintf(stderr, "error: too many macro arguments - aborting\n");
exit(1);
@@ -839,14 +784,12 @@ static void def_add_arg(void)
check_for_max_args();
/* Remove trailing white space and, if necessary, opening brace. */
while (isspace((int)yytext[length - 1]))
length--;
while (isspace((int)yytext[length - 1])) length--;
/* This can happen because we are also processing "argv[0]", the
macro name, as a pseudo-argument. The lexor will match that
as name(, so chop off the ( here. */
if (yytext[length - 1] == '(')
length--;
if (yytext[length - 1] == '(') length--;
yytext[length] = 0;
@@ -921,41 +864,32 @@ void define_macro(const char* name, const char* value, int keyword, int argc)
}
}
if (def_table == 0)
if (def_table == 0) {
def_table = def;
else
{
} else {
struct define_t* cur = def_table;
while (1)
{
while (1) {
int cmp = strcmp(def->name, cur->name);
if (cmp == 0)
{
if (cmp == 0) {
free(cur->value);
cur->value = def->value;
free(def->name);
free(def);
break;
}
else if (cmp < 0)
{
if (cur->left != 0)
} else if (cmp < 0) {
if (cur->left != 0) {
cur = cur->left;
else
{
} else {
cur->left = def;
def->up = cur;
break;
}
}
else
{
if (cur->right != 0)
} else {
if (cur->right != 0) {
cur = cur->right;
else
{
} else {
cur->right = def;
def->up = cur;
break;
@@ -973,8 +907,7 @@ static void free_macro(struct define_t* def)
free_macro(def->right);
free(def->name);
free(def->value);
for (idx = 0 ; idx < def->argc ; idx += 1)
free(def->defaults[idx]);
for (idx = 0 ; idx < def->argc ; idx += 1) free(def->defaults[idx]);
free(def->defaults);
free(def);
}
@@ -1069,25 +1002,19 @@ static void do_define(void)
*/
cp = strchr(yytext, '/');
while (cp && *cp)
{
while (cp && *cp) {
if (cp[1] == '/') {
*cp = 0;
break;
}
if (cp[1] == '*')
{
if (cp[1] == '*') {
tail = strstr(cp+2, "*/");
if (tail == 0)
{
if (tail == 0) {
*cp = 0;
fprintf
(
stderr,
"%s:%u: Unterminated comment in define\n",
istack->path, istack->lineno+1
fprintf(stderr, "%s:%u: Unterminated comment in define\n",
istack->path, istack->lineno+1
);
break;
}
@@ -1101,10 +1028,8 @@ static void do_define(void)
/* Trim trailing white space. */
cp = yytext + strlen(yytext);
while (cp > yytext)
{
if (!isspace((int)cp[-1]))
break;
while (cp > yytext) {
if (!isspace((int)cp[-1])) break;
cp -= 1;
*cp = 0;
@@ -1114,8 +1039,7 @@ static void do_define(void)
* and the white space that precedes it, then replace all that
* with a single newline.
*/
if ((cp > yytext) && (cp[-1] == '\\'))
{
if ((cp > yytext) && (cp[-1] == '\\')) {
cp -= 1;
cp[0] = 0;
@@ -1143,18 +1067,13 @@ static void do_define(void)
/* If the text for a macro with arguments contains occurrences
* of ARG_MARK, issue an error message and suppress the macro.
*/
if ((def_argc > 1) && strchr(head, ARG_MARK))
{
if ((def_argc > 1) && strchr(head, ARG_MARK)) {
emit_pathline(istack);
error_count += 1;
def_argc = 0;
fprintf
(
stderr,
"error: implementation restriction - macro text may not contain a %s character\n",
_STR2(ARG_MARK)
);
fprintf(stderr, "error: implementation restriction - "
"macro text may not contain a %s character\n", _STR2(ARG_MARK));
}
/* Look for formal argument names in the definition, and replace
@@ -1162,18 +1081,15 @@ static void do_define(void)
* the formal argument index number.
*/
added_cnt = 0;
for (arg = 1; arg < def_argc; arg++)
{
for (arg = 1; arg < def_argc; arg++) {
int argl = def_argl[arg];
cp = find_arg(head, head, def_argv(arg));
while (cp && *cp)
{
while (cp && *cp) {
added_cnt += 2 - argl;
if (added_cnt > 0)
{
if (added_cnt > 0) {
char* base = define_text;
define_cnt += added_cnt;
@@ -1216,13 +1132,11 @@ static void def_finish(void)
{
define_continue_flag = 0;
if (def_argc <= 0)
return;
if (def_argc <= 0) return;
if (!define_text)
if (!define_text) {
define_macro(def_argv(0), "", 0, def_argc);
else
{
} else {
define_macro(def_argv(0), define_text, 0, def_argc);
free(define_text);
@@ -1251,24 +1165,18 @@ static void def_undefine(void)
if (cur == 0) return;
if (cur->magic) return;
if (cur->up == 0)
{
if ((cur->left == 0) && (cur->right == 0))
if (cur->up == 0) {
if ((cur->left == 0) && (cur->right == 0)) {
def_table = 0;
else if (cur->left == 0)
{
} else if (cur->left == 0) {
def_table = cur->right;
if (cur->right)
cur->right->up = 0;
}
else if (cur->right == 0)
{
} else if (cur->right == 0) {
assert(cur->left);
def_table = cur->left;
def_table->up = 0;
}
else
{
} else {
tail = cur->left;
while (tail->right)
tail = tail->right;
@@ -1279,50 +1187,40 @@ static void def_undefine(void)
def_table = cur->left;
def_table->up = 0;
}
}
else if (cur->left == 0)
{
if (cur->up->left == cur)
} else if (cur->left == 0) {
if (cur->up->left == cur) {
cur->up->left = cur->right;
else
{
} else {
assert(cur->up->right == cur);
cur->up->right = cur->right;
}
if (cur->right)
cur->right->up = cur->up;
if (cur->right) cur->right->up = cur->up;
}
else if (cur->right == 0)
{
else if (cur->right == 0) {
assert(cur->left);
if (cur->up->left == cur)
if (cur->up->left == cur) {
cur->up->left = cur->left;
else
{
} else {
assert(cur->up->right == cur);
cur->up->right = cur->left;
}
cur->left->up = cur->up;
}
else
{
} else {
tail = cur->left;
assert(cur->left && cur->right);
while (tail->right)
tail = tail->right;
while (tail->right) tail = tail->right;
tail->right = cur->right;
tail->right->up = tail;
if (cur->up->left == cur)
if (cur->up->left == cur) {
cur->up->left = cur->left;
else
{
} else {
assert(cur->up->right == cur);
cur->up->right = cur->left;
}
@@ -1332,8 +1230,7 @@ static void def_undefine(void)
free(cur->name);
free(cur->value);
for (idx = 0 ; idx < cur->argc ; idx += 1)
free(cur->defaults[idx]);
for (idx = 0 ; idx < cur->argc ; idx += 1) free(cur->defaults[idx]);
free(cur->defaults);
free(cur);
}
@@ -1350,10 +1247,9 @@ static int macro_needs_args(const char*text)
{
cur_macro = def_lookup(text);
if (cur_macro)
if (cur_macro) {
return (cur_macro->argc > 1);
else
{
} else {
emit_pathline(istack);
fprintf(stderr, "warning: macro %s undefined (and assumed null) at this point.\n", text);
return 0;
@@ -1386,8 +1282,7 @@ static void macro_add_to_arg(int is_white_space)
check_for_max_args();
/* Replace any run of white space with a single space */
if (is_white_space)
{
if (is_white_space) {
yytext[0] = ' ';
yytext[1] = 0;
length = 1;
@@ -1435,8 +1330,7 @@ static int exp_buf_free = 0;
static void exp_buf_grow_to_fit(int length)
{
while (length >= exp_buf_free)
{
while (length >= exp_buf_free) {
exp_buf_size += EXP_BUF_CHUNK;
exp_buf_free += EXP_BUF_CHUNK;
exp_buf = realloc(exp_buf, exp_buf_size);
@@ -1451,8 +1345,7 @@ static void expand_using_args(void)
int arg;
int length;
if (def_argc != cur_macro->argc)
{
if (def_argc != cur_macro->argc) {
emit_pathline(istack);
fprintf(stderr, "error: wrong number of arguments for `%s\n", cur_macro->name);
return;
@@ -1461,12 +1354,10 @@ static void expand_using_args(void)
head = cur_macro->value;
tail = head;
while (*tail)
{
if (*tail != ARG_MARK)
while (*tail) {
if (*tail != ARG_MARK) {
tail++;
else
{
} else {
arg = tail[1]; assert(arg < def_argc);
char*use_argv;
@@ -1508,17 +1399,14 @@ static void expand_using_args(void)
*/
static void do_expand(int use_args)
{
if (cur_macro)
{
if (cur_macro) {
struct include_stack_t*isp;
int head = 0;
int tail = 0;
const char *cp;
unsigned escapes = 0;
char *str_buf = 0;
if (cur_macro->keyword)
{
if (cur_macro->keyword) {
fprintf(yyout, "%s", cur_macro->value);
if (do_expand_stringify_flag) {
do_expand_stringify_flag = 0;
@@ -1527,33 +1415,27 @@ static void do_expand(int use_args)
return;
}
if (use_args)
{
if (use_args) {
int tail = 0;
head = exp_buf_size - exp_buf_free;
expand_using_args();
tail = exp_buf_size - exp_buf_free;
exp_buf_free += tail - head;
if (tail == head)
return;
if (tail == head) return;
}
isp = (struct include_stack_t*) calloc(1, sizeof(struct include_stack_t));
isp->stringify_flag = do_expand_stringify_flag;
do_expand_stringify_flag = 0;
if (use_args)
{
if (use_args) {
isp->str = &exp_buf[head];
}
else if(cur_macro->magic)
{
} else if(cur_macro->magic) {
// cast const char * to char * to suppress warning, since we won't
// be modifying isp->str in place.
isp->str = (char*)do_magic(cur_macro->name);
}
else
{
} else {
isp->str = cur_macro->value;
}
@@ -1588,8 +1470,7 @@ static void do_expand(int use_args)
exp_buf_free -= idx;
isp->str = str_buf;
} else
isp->str = strdup(isp->str);
} else isp->str = strdup(isp->str);
isp->orig_str = isp->str;
isp->next = istack;
@@ -1612,21 +1493,16 @@ static const char* do_magic(const char*name)
{
size_t desired_cnt = 0;
if(!magic_text)
{
magic_text = malloc(24); // unimportant initial size
}
if(!magic_text) magic_text = malloc(24); // unimportant initial size
if(!strcmp(name, "__LINE__"))
{
if(!strcmp(name, "__LINE__")) {
// istack->lineno is unsigned. the largest it could be is 64 bits.
// 2^64 is between 10^19 and 10^20. So the decimal representation of
// lineno can't possibly be longer than 23 bytes. I'm generous but
// bytes are cheap and this is nobody's critical path.
desired_cnt = 24;
if(magic_cnt < desired_cnt)
{
if(magic_cnt < desired_cnt) {
magic_text = realloc(magic_text, desired_cnt);
assert(magic_text);
magic_cnt = desired_cnt;
@@ -1637,17 +1513,12 @@ static const char* do_magic(const char*name)
assert(actual_len >= 0);
assert((unsigned) actual_len < desired_cnt);
return magic_text;
}
else if(!strcmp(name, "__FILE__"))
{
} else if(!strcmp(name, "__FILE__")) {
const char *path = get_path(istack);
if(path)
{
if(path) {
desired_cnt = strlen(path)+2+1; // two quotes and a null
if(magic_cnt < desired_cnt)
{
if(magic_cnt < desired_cnt) {
magic_text = realloc(magic_text, desired_cnt);
assert(magic_text);
magic_cnt = desired_cnt;
@@ -1689,19 +1560,17 @@ static const char* do_magic(const char*name)
static void output_init(void)
{
if (line_direct_flag)
if (line_direct_flag) {
fprintf(yyout, "`line 1 \"%s\" 0\n", istack->path);
}
}
static void include_filename(void)
{
if(standby) {
emit_pathline(istack);
fprintf
(
stderr,
"error: malformed `include directive. Extra junk on line?\n"
);
fprintf(stderr,
"error: malformed `include directive. Extra junk on line?\n");
exit(1);
}
@@ -1728,8 +1597,7 @@ static void do_include(void)
/* Add the current path to the start of the include_dir list. */
isp = istack;
while(isp && (isp->path == NULL))
isp = isp->next;
while(isp && (isp->path == NULL)) isp = isp->next;
assert(isp);
@@ -1775,8 +1643,9 @@ code_that_switches_buffers:
}
}
if (line_direct_flag)
if (line_direct_flag) {
fprintf(yyout, "\n`line 1 \"%s\" 1\n", standby->path);
}
standby->next = istack;
standby->stringify_flag = 0;
@@ -1796,8 +1665,7 @@ code_that_switches_buffers:
*/
static unsigned get_line(struct include_stack_t* isp)
{
while(isp && (isp->path == NULL))
isp = isp->next;
while(isp && (isp->path == NULL)) isp = isp->next;
assert(isp);
@@ -1811,8 +1679,7 @@ static unsigned get_line(struct include_stack_t* isp)
*/
static const char* get_path(struct include_stack_t* isp)
{
while(isp && (isp->path == NULL))
isp = isp->next;
while(isp && (isp->path == NULL)) isp = isp->next;
assert(isp);
@@ -1827,8 +1694,7 @@ static const char* get_path(struct include_stack_t* isp)
*/
static void emit_pathline(struct include_stack_t* isp)
{
while(isp && (isp->path == NULL))
isp = isp->next;
while(isp && (isp->path == NULL)) isp = isp->next;
assert(isp);
@@ -1837,17 +1703,12 @@ static void emit_pathline(struct include_stack_t* isp)
static void lexor_done(void)
{
while (ifdef_stack)
{
while (ifdef_stack) {
struct ifdef_stack_t*cur = ifdef_stack;
ifdef_stack = cur->next;
fprintf
(
stderr,
"%s:%u: error: This `ifdef lacks an `endif.\n",
cur->path, cur->lineno+1
);
fprintf(stderr, "%s:%u: error: This `ifdef lacks an `endif.\n",
cur->path, cur->lineno+1);
free(cur->path);
free(cur);
@@ -1904,8 +1765,7 @@ static void open_input_file(struct include_stack_t*isp)
char*cmd = malloc(cmdlen);
snprintf(cmd, cmdlen, "%s -w\"%s\"%s %s", vhdlpp_path, vhdlpp_work, libs, isp->path);
if (verbose_flag)
fprintf(stderr, "Invoke vhdlpp: %s\n", cmd);
if (verbose_flag) fprintf(stderr, "Invoke vhdlpp: %s\n", cmd);
isp->file = popen(cmd, "r");
isp->file_close = pclose;
@@ -1943,29 +1803,23 @@ static int load_next_input(void)
isp->comment = NULL;
}
if (isp->file)
{
if (isp->file) {
free(isp->path);
assert(isp->file_close);
isp->file_close(isp->file);
}
else
{
} else {
/* If I am printing line directives and I just finished
* macro substitution, I should terminate the line and
* arrange for a new directive to be printed.
*/
if (line_direct_flag && istack && istack->path && isp->lineno)
if (line_direct_flag && istack && istack->path && isp->lineno) {
fprintf(yyout, "\n");
else
line_mask_flag = 1;
} else line_mask_flag = 1;
free(isp->orig_str);
}
if (isp->stringify_flag) {
fputc('"', yyout);
}
if (isp->stringify_flag) fputc('"', yyout);
free(isp);
@@ -1974,10 +1828,8 @@ static int load_next_input(void)
* queue. If none are there, give up. Otherwise, open the file
* and continue parsing.
*/
if (istack == 0)
{
if (file_queue == 0)
{
if (istack == 0) {
if (file_queue == 0) {
lexor_done();
return 0;
}
@@ -1989,15 +1841,15 @@ static int load_next_input(void)
istack->lineno = 0;
open_input_file(istack);
if (istack->file == 0)
{
if (istack->file == 0) {
perror(istack->path);
error_count += 1;
return 0;
}
if (line_direct_flag)
if (line_direct_flag) {
fprintf(yyout, "\n`line 1 \"%s\" 0\n", istack->path);
}
if (depend_file) {
if (dep_mode == 'p') {
@@ -2022,8 +1874,9 @@ static int load_next_input(void)
*/
yy_switch_to_buffer(istack->yybs);
if (line_direct_flag && istack->path && !line_mask_flag)
if (line_direct_flag && istack->path && !line_mask_flag) {
fprintf(yyout, "\n`line %u \"%s\" 2\n", istack->lineno+1, istack->path);
}
return 1;
}
@@ -2051,17 +1904,14 @@ static void do_dump_precompiled_defines(FILE* out, struct define_t* table)
fprintf(out, "%s:%d:%zd:%s\n", table->name, table->argc, strlen(table->value), table->value);
#endif
if (table->left)
do_dump_precompiled_defines(out, table->left);
if (table->left) do_dump_precompiled_defines(out, table->left);
if (table->right)
do_dump_precompiled_defines(out, table->right);
if (table->right) do_dump_precompiled_defines(out, table->right);
}
void dump_precompiled_defines(FILE* out)
{
if (def_table)
do_dump_precompiled_defines(out, def_table);
if (def_table) do_dump_precompiled_defines(out, def_table);
}
void load_precompiled_defines(FILE* src)
@@ -2070,8 +1920,7 @@ void load_precompiled_defines(FILE* src)
size_t buf_len = 4096;
int ch;
while ((ch = fgetc(src)) != EOF)
{
while ((ch = fgetc(src)) != EOF) {
char* cp = buf;
char* name = 0;
@@ -2086,26 +1935,21 @@ void load_precompiled_defines(FILE* src)
assert( (size_t)(cp-buf) < buf_len );
}
if (ch != ':')
return;
if (ch != ':') return;
/* Terminate the name string. */
*cp++ = 0;
assert( (size_t)(cp-buf) < buf_len );
/* Read the argc number. (this doesn't need buffer space) */
while (isdigit(ch = fgetc(src)))
argc = 10*argc + ch-'0';
while (isdigit(ch = fgetc(src))) argc = 10*argc + ch-'0';
if (ch != ':')
return;
if (ch != ':') return;
/* Read the value len (this doesn't need buffer space) */
while (isdigit(ch = fgetc(src)))
len = 10*len + ch-'0';
while (isdigit(ch = fgetc(src))) len = 10*len + ch-'0';
if (ch != ':')
return;
if (ch != ':') return;
/* Save the name, and start the buffer over. */
name = strdup(buf);
@@ -2119,8 +1963,7 @@ void load_precompiled_defines(FILE* src)
cp = buf;
while (len > 0)
{
while (len > 0) {
ch = fgetc(src);
if (ch == EOF) {
free(name);
@@ -2165,8 +2008,7 @@ void reset_lexor(FILE* out, char* paths[])
isp->stringify_flag = 0;
isp->comment = NULL;
if (isp->file == 0)
{
if (isp->file == 0) {
perror(paths[0]);
exit(1);
}
@@ -2189,8 +2031,7 @@ void reset_lexor(FILE* out, char* paths[])
/* Now build up a queue of all the remaining file names, so
* that load_next_input() can pull them when needed.
*/
for (idx = 1 ; paths[idx] ; idx += 1)
{
for (idx = 1 ; paths[idx] ; idx += 1) {
isp = malloc(sizeof(struct include_stack_t));
isp->path = strdup(paths[idx]);
isp->file = 0;
@@ -2200,10 +2041,8 @@ void reset_lexor(FILE* out, char* paths[])
isp->stringify_flag = 0;
isp->comment = NULL;
if (tail)
tail->next = isp;
else
file_queue = isp;
if (tail) tail->next = isp;
else file_queue = isp;
tail = isp;
}
+9 -1
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2014 Stephen Williams (steve@icarus.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
@@ -45,6 +45,14 @@ bool Nexus::drivers_constant() const
return false;
}
/* If we are connected to a tran, there may be a driver
on the other side of the tran. We could try checking
for this, but for now, be pessimistic. */
if (dynamic_cast<const NetTran*>(cur->get_obj())) {
driven_ = VAR;
return false;
}
Link::DIR cur_dir = cur->get_dir();
if (cur_dir == Link::INPUT)
continue;
+1
View File
@@ -859,6 +859,7 @@ int main(int argc, char*argv[])
# if defined(HAVE_TIMES)
times_flag = true;
# endif
flags["VVP_EXTRA_ARGS"] = strdup(" -v");
break;
case 'V':
version_flag = true;
+3 -2
View File
@@ -101,11 +101,12 @@ uint64_t Design::scale_to_precision(uint64_t val,
return val;
}
NetScope* Design::make_root_scope(perm_string root, bool program_block)
NetScope* Design::make_root_scope(perm_string root, bool program_block,
bool is_interface)
{
NetScope *root_scope_;
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE,
false, program_block);
false, program_block, is_interface);
/* This relies on the fact that the basename return value is
permallocated. */
root_scope_->set_module_name(root_scope_->basename());
+4 -2
View File
@@ -110,8 +110,10 @@ void Definitions::add_class(netclass_t*net_class)
* in question.
*/
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest, bool prog)
: type_(t), name_(n), nested_module_(nest), program_block_(prog), up_(up)
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, bool nest,
bool program, bool interface)
: type_(t), name_(n), nested_module_(nest), program_block_(program),
is_interface_(interface), up_(up)
{
events_ = 0;
lcounter_ = 0;
+8 -3
View File
@@ -918,7 +918,8 @@ class NetScope : public Definitions, public Attrib {
/* Create a new scope, and attach it to the given parent. The
name is expected to have been permallocated. */
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false, bool prog=false);
NetScope(NetScope*up, const hname_t&name, TYPE t, bool nest=false,
bool program=false, bool interface=false);
~NetScope();
/* Rename the scope using the name generated by inserting as
@@ -1008,8 +1009,9 @@ class NetScope : public Definitions, public Attrib {
// Nested modules have slightly different scope search rules.
inline bool nested_module() const { return nested_module_; }
// Program blocks have elaboration constraints.
// Program blocks and interfaces have elaboration constraints.
inline bool program_block() const { return program_block_; }
inline bool is_interface() const { return is_interface_; }
TYPE type() const;
void print_type(ostream&) const;
@@ -1221,6 +1223,8 @@ class NetScope : public Definitions, public Attrib {
bool nested_module_;
// True if the scope is a program block
bool program_block_;
// True if the scope is an interface
bool is_interface_;
perm_string file_;
perm_string def_file_;
@@ -4747,7 +4751,8 @@ class Design : public Definitions {
const char* get_flag(const string&key) const;
NetScope* make_root_scope(perm_string name, bool program_block);
NetScope* make_root_scope(perm_string name, bool program_block,
bool is_interface);
NetScope* find_root_scope();
std::list<NetScope*> find_root_scopes() const;
+6
View File
@@ -34,6 +34,12 @@ netparray_t::~netparray_t()
* The packed width of a packed array is the packed width of the
* element times the dimension width of the array itself.
*/
bool netparray_t::packed(void) const
{
return true;
}
long netparray_t::packed_width(void) const
{
long cur_width = element_type()->packed_width();
+1
View File
@@ -64,6 +64,7 @@ class netparray_t : public netsarray_t {
public:
// Virtual methods from the ivl_type_s type...
bool packed(void) const;
long packed_width(void) const;
std::vector<netrange_t> slice_dimensions() const;
+68 -26
View File
@@ -562,8 +562,8 @@ static void current_function_set_statement(const YYLTYPE&loc, vector<Statement*>
%type <statement> udp_initial udp_init_opt
%type <expr> udp_initial_expr_opt
%type <text> register_variable net_variable endlabel_opt class_declaration_endlabel_opt
%type <perm_strings> register_variable_list net_variable_list
%type <text> register_variable net_variable event_variable endlabel_opt class_declaration_endlabel_opt
%type <perm_strings> register_variable_list net_variable_list event_variable_list
%type <perm_strings> list_of_identifiers loop_variables
%type <port_list> list_of_port_identifiers
@@ -1117,8 +1117,8 @@ data_type_or_implicit_or_void
statements may go. This may be a bad idea, but it is legacy now. */
/* NOTE 2: The "module" rule of the description combines the
module_declaration and program_declaration rules from the
standard description. */
module_declaration, program_declaration, and interface_declaration
rules from the standard description. */
description /* IEEE1800-2005: A.1.2 */
: module
@@ -2186,8 +2186,8 @@ block_item_decl
{ if ($2) pform_set_data_type(@2, $2, $3, NetNet::REG, attributes_in_context);
}
| K_event list_of_identifiers ';'
{ pform_make_events($2, @1.text, @1.first_line);
| K_event event_variable_list ';'
{ if ($2) pform_make_events($2, @1.text, @1.first_line);
}
| K_parameter param_type parameter_assign_list ';'
@@ -4213,13 +4213,13 @@ local_timeunit_prec_decl2
}
;
/* This is the global structure of a module. A module in a start
/* This is the global structure of a module. A module is a start
section, with optional ports, then an optional list of module
items, and finally an end marker. */
module
: attribute_list_opt module_start IDENTIFIER
{ pform_startmodule(@2, $3, $2==K_program, $1); }
{ pform_startmodule(@2, $3, $2==K_program, $2==K_interface, $1); }
module_package_import_list_opt
module_parameter_port_list_opt
module_port_list_opt
@@ -4258,6 +4258,9 @@ module
case K_program:
yyerror(@14, "error: program not closed by endprogram.");
break;
case K_interface:
yyerror(@14, "error: interface not closed by endinterface.");
break;
default:
break;
}
@@ -4283,6 +4286,10 @@ module
yyerror(@16, "error: End label doesn't match "
"program name.");
break;
case K_interface:
yyerror(@16, "error: End label doesn't match "
"interface name.");
break;
default:
break;
}
@@ -4297,19 +4304,21 @@ module
}
;
/* Modules start with module/macromodule or program keyword, and end
with the endmodule or endprogram keyword. The syntax for modules
and programs is almost identical, so let semantics sort out the
differences. */
/* Modules start with a module/macromodule, program, or interface
keyword, and end with a endmodule, endprogram, or endinterface
keyword. The syntax for modules programs, and interfaces is
almost identical, so let semantics sort out the differences. */
module_start
: K_module { $$ = K_module; }
| K_macromodule { $$ = K_module; }
| K_program { $$ = K_program; }
| K_interface { $$ = K_interface; }
;
module_end
: K_endmodule { $$ = K_module; }
| K_endprogram { $$ = K_program; }
: K_endmodule { $$ = K_module; }
| K_endprogram { $$ = K_program; }
| K_endinterface { $$ = K_interface; }
;
endlabel_opt
@@ -4505,7 +4514,12 @@ module_item
/* */
| K_defparam defparam_assign_list ';'
| K_defparam
{ if (pform_in_interface())
yyerror(@1, "error: Parameter overrides are not allowed "
"in interfaces.");
}
defparam_assign_list ';'
/* Most gate types have an optional drive strength and optional
two/three-value delay. These rules handle the different cases.
@@ -4674,21 +4688,26 @@ module_item
/* 1364-2001 and later allow specparam declarations outside specify blocks. */
| attribute_list_opt K_specparam specparam_decl ';'
| attribute_list_opt K_specparam
{ if (pform_in_interface())
yyerror(@1, "error: specparam declarations are not allowed "
"in interfaces.");
}
specparam_decl ';'
/* specify blocks are parsed but ignored. */
| K_specify K_endspecify
{ /* empty lists are legal syntax. */ }
| K_specify
{ if (pform_in_interface())
yyerror(@1, "error: specify blocks are not allowed "
"in interfaces.");
}
specify_item_list_opt K_endspecify
| K_specify specify_item_list K_endspecify
{
}
| K_specify error K_endspecify
{ yyerror(@1, "error: syntax error in specify block");
yyerrok;
}
| K_specify error K_endspecify
{ yyerror(@1, "error: syntax error in specify block");
yyerrok;
}
/* These rules match various errors that the user can type into
module items. These rules try to catch them at a point where a
@@ -5338,6 +5357,23 @@ net_variable_list
}
;
event_variable
: IDENTIFIER dimensions_opt
{ if ($2) {
yyerror(@2, "sorry: event arrays are not supported.");
delete $2;
}
$$ = $1;
}
;
event_variable_list
: event_variable
{ $$ = list_from_identifier($1); }
| event_variable_list ',' event_variable
{ $$ = list_from_identifier($1, $3); }
;
specify_item
: K_specparam specparam_decl ';'
| specify_simple_path_decl ';'
@@ -5450,6 +5486,12 @@ specify_item_list
| specify_item_list specify_item
;
specify_item_list_opt
: /* empty */
{ }
| specify_item_list
{ }
specify_edge_path_decl
: specify_edge_path '=' '(' delay_value_list ')'
{ $$ = pform_assign_path_delay($1, $4); }
+39 -9
View File
@@ -534,6 +534,15 @@ bool pform_in_program_block()
return false;
}
bool pform_in_interface()
{
if (pform_cur_module.empty())
return false;
if (pform_cur_module.front()->is_interface)
return true;
return false;
}
static bool pform_at_module_level()
{
return (lexical_scope == pform_cur_module.front())
@@ -1107,7 +1116,8 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
}
void pform_startmodule(const struct vlltype&loc, const char*name,
bool program_block, list<named_pexpr_t>*attr)
bool program_block, bool is_interface,
list<named_pexpr_t>*attr)
{
if (! pform_cur_module.empty() && !gn_system_verilog()) {
cerr << loc << ": error: Module definition " << name
@@ -1115,15 +1125,25 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
error_count += 1;
}
if (gn_system_verilog() && ! pform_cur_module.empty() &&
pform_cur_module.front()->program_block) {
cerr << loc << ": error: Program blocks cannot contain nested modules/program blocks." << endl;
error_count += 1;
if (gn_system_verilog() && ! pform_cur_module.empty()) {
if (pform_cur_module.front()->program_block) {
cerr << loc << ": error: module, program, or interface "
"declarations are not allowed in program "
"blocks." << endl;
error_count += 1;
}
if (pform_cur_module.front()->is_interface
&& !(program_block || is_interface)) {
cerr << loc << ": error: module declarations are not "
"allowed in interfaces." << endl;
error_count += 1;
}
}
perm_string lex_name = lex_strings.make(name);
Module*cur_module = new Module(lexical_scope, lex_name);
cur_module->program_block = program_block;
cur_module->is_interface = is_interface;
/* Set the local time unit/precision to the global value. */
cur_module->time_unit = pform_time_unit;
cur_module->time_precision = pform_time_prec;
@@ -2001,8 +2021,13 @@ void pform_makegates(const struct vlltype&loc,
{
assert(! pform_cur_module.empty());
if (pform_cur_module.front()->program_block) {
cerr << loc << ": error: Gates and switches may not be instantiated"
<< " in program blocks." << endl;
cerr << loc << ": error: Gates and switches may not be instantiated in "
<< "program blocks." << endl;
error_count += 1;
}
if (pform_cur_module.front()->is_interface) {
cerr << loc << ": error: Gates and switches may not be instantiated in "
<< "interfaces." << endl;
error_count += 1;
}
@@ -2117,8 +2142,13 @@ void pform_make_modgates(const struct vlltype&loc,
{
assert(! pform_cur_module.empty());
if (pform_cur_module.front()->program_block) {
cerr << loc << ": error: Module instantiations are not allowed"
<< " in program blocks." << endl;
cerr << loc << ": error: Module instantiations are not allowed in "
<< "program blocks." << endl;
error_count += 1;
}
if (pform_cur_module.front()->is_interface) {
cerr << loc << ": error: Module instantiations are not allowed in "
<< "interfaces." << endl;
error_count += 1;
}
+9 -3
View File
@@ -136,6 +136,10 @@ extern void pform_set_default_nettype(NetNet::Type net,
used to reject statements that cannot exist in program blocks. */
extern bool pform_in_program_block(void);
/* Return true if currently processing an interface. This can be
used to reject statements that cannot exist in interfaces. */
extern bool pform_in_interface(void);
/*
* Look for the given wire in the current lexical scope. If the wire
* (including variables of any type) cannot be found in the current
@@ -152,12 +156,14 @@ extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_ty
* are to apply to the scope of that module. The endmodule causes the
* pform to close up and finish the named module.
*
* The program_flag indicates that the module is actually a program
* block. This has implications during parse and during
* The program_block flag indicates that the module is actually a program
* block. The is_interface flag indicates that the module is actually
* an interface. These flags have implications during parse and during
* elaboration/code generation.
*/
extern void pform_startmodule(const struct vlltype&loc, const char*name,
bool program_block, list<named_pexpr_t>*attr);
bool program_block, bool is_interface,
list<named_pexpr_t>*attr);
extern void pform_check_timeunit_prec();
extern void pform_module_set_ports(vector<Module::port_t*>*);
+13 -7
View File
@@ -531,18 +531,24 @@ bool NetCase::synth_async(Design*des, NetScope*scope,
statement_map[sel_idx] = items_[item].statement;
}
// The mux_size is the number of inputs that are selected.
unsigned mux_size = max_guard_value + 1;
unsigned sel_need = ceil(log2(mux_size));
// The minimum selector width is the number of inputs that
// are selected, rounded up to the nearest power of 2.
unsigned sel_need = ceil(log2(max_guard_value + 1));
// If the sel_width can select more than just the explicit
// guard values, and there is a default statement, then adjust
// the mux size to allow for the implicit selections.
if (statement_default && (sel_width > sel_need)) {
// the sel_need to allow for the implicit selections.
if (statement_default && (sel_width > sel_need))
sel_need += 1;
ivl_assert(*this, sel_need < sizeof mux_size);
mux_size = 1<<sel_need;
// The mux size is always an exact power of 2.
if (sel_need >= 8*sizeof(unsigned)) {
cerr << get_fileline() << ": sorry: mux select width of "
<< sel_need << " bits is too large for synthesis." << endl;
des->errors += 1;
return false;
}
unsigned mux_size = 1U << sel_need;
if (debug_synth2) {
cerr << get_fileline() << ": NetCase::synth_async: "
+13 -3
View File
@@ -78,6 +78,7 @@ static void emit_bits(const char *bits, unsigned nbits, unsigned is_signed)
{
unsigned has_undef = 0;
assert(nbits > 0);
/* Check for an undefined bit. */
for (int idx = (int)nbits-1; idx >= 0; idx -= 1) {
if ((bits[idx] != '0') && (bits[idx] != '1')) {
@@ -91,8 +92,14 @@ static void emit_bits(const char *bits, unsigned nbits, unsigned is_signed)
/* Emit as a binary constant. */
if (has_undef || (nbits < 2)) {
int start = nbits - 1;
char sbit = bits[start];
/* Trim extra leading bits. */
if (! is_signed && (sbit == '1')) sbit = ' ';
while (start && (sbit == bits[start-1])) start -= 1;
/* Print the trimmed value. */
fprintf(vlog_out, "b");
for (int idx = (int)nbits-1; idx >= 0; idx -= 1) {
for (int idx = start; idx >= 0; idx -= 1) {
fprintf(vlog_out, "%c", bits[idx]);
}
/* Emit as a hex constant. */
@@ -152,9 +159,12 @@ void emit_number(const char *bits, unsigned nbits, unsigned is_signed,
vlog_errors += 1;
return;
} else if (rtype == -2) {
fprintf(vlog_out, "'bz");
fprintf(vlog_out, "%u'bz", nbits);
} else if (rtype == -3) {
fprintf(vlog_out, "'bx");
/* If this is a 32-bit wide constant then generate the
* undefined with integers to get a signed value. */
if (nbits == 32) fprintf(vlog_out, "1/0");
else fprintf(vlog_out, "%u'bx", nbits);
} else {
fprintf(vlog_out, "%"PRId32, value);
}
+46 -37
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2005-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2005-2014 Stephen Williams (steve@icarus.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
@@ -36,7 +36,6 @@ static void function_argument_logic(ivl_signal_t port, ivl_expr_t expr)
if (ewidth < pwidth)
fprintf(vvp_out, " %%pad/u %u;\n", pwidth);
fprintf(vvp_out, " %%store/vec4 v%p_0, 0, %u;\n", port, pwidth);
}
static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
@@ -45,54 +44,57 @@ static void function_argument_real(ivl_signal_t port, ivl_expr_t expr)
assert(ivl_signal_dimensions(port) == 0);
draw_eval_real(expr);
fprintf(vvp_out, " %%store/real v%p_0;\n", port);
}
static void function_argument_bool(ivl_signal_t port, ivl_expr_t expr)
{
/* For now, treat bit2 variables as bit4 variables. */
function_argument_logic(port, expr);
}
static void function_argument_class(ivl_signal_t port, ivl_expr_t expr)
{
draw_eval_object(expr);
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
}
static void function_argument_darray(ivl_signal_t port, ivl_expr_t expr)
{
draw_eval_object(expr);
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
}
static void function_argument_string(ivl_signal_t port, ivl_expr_t expr)
{
draw_eval_string(expr);
fprintf(vvp_out, " %%store/str v%p_0;\n", port);
}
static void draw_function_argument(ivl_signal_t port, ivl_expr_t expr)
static void draw_eval_function_argument(ivl_signal_t port, ivl_expr_t expr)
{
ivl_variable_type_t dtype = ivl_signal_data_type(port);
switch (dtype) {
case IVL_VT_BOOL:
/* For now, treat bit2 variables as bit4 variables. */
case IVL_VT_LOGIC:
function_argument_logic(port, expr);
break;
case IVL_VT_REAL:
function_argument_real(port, expr);
break;
case IVL_VT_BOOL:
function_argument_bool(port, expr);
break;
case IVL_VT_CLASS:
function_argument_class(port, expr);
draw_eval_object(expr);
break;
case IVL_VT_STRING:
function_argument_string(port, expr);
draw_eval_string(expr);
break;
case IVL_VT_DARRAY:
function_argument_darray(port, expr);
draw_eval_object(expr);
break;
default:
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
ivl_signal_basename(port), dtype);
assert(0);
}
}
static void draw_send_function_argument(ivl_signal_t port)
{
ivl_variable_type_t dtype = ivl_signal_data_type(port);
switch (dtype) {
case IVL_VT_BOOL:
/* For now, treat bit2 variables as bit4 variables. */
case IVL_VT_LOGIC:
fprintf(vvp_out, " %%store/vec4 v%p_0, 0, %u;\n",
port, ivl_signal_width(port));
break;
case IVL_VT_REAL:
fprintf(vvp_out, " %%store/real v%p_0;\n", port);
break;
case IVL_VT_CLASS:
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
break;
case IVL_VT_STRING:
fprintf(vvp_out, " %%store/str v%p_0;\n", port);
break;
case IVL_VT_DARRAY:
fprintf(vvp_out, " %%store/obj v%p_0;\n", port);
break;
default:
fprintf(stderr, "XXXX function argument %s type=%d?!\n",
@@ -111,13 +113,20 @@ static void draw_ufunc_preamble(ivl_expr_t expr)
fprintf(vvp_out, " %%alloc S_%p;\n", def);
}
/* evaluate the expressions and send the results to the
function ports. */
/* Evaluate the expressions and send the results to the
function ports. Do this in two passes - evaluate,
then send - this avoids the function input variables
being overwritten if the same (non-automatic) function
is called in one of the exressions. */
assert(ivl_expr_parms(expr) == (ivl_scope_ports(def)-1));
for (idx = 0 ; idx < ivl_expr_parms(expr) ; idx += 1) {
ivl_signal_t port = ivl_scope_port(def, idx+1);
draw_function_argument(port, ivl_expr_parm(expr, idx));
draw_eval_function_argument(port, ivl_expr_parm(expr, idx));
}
for (idx = ivl_expr_parms(expr) ; idx > 0 ; idx -= 1) {
ivl_signal_t port = ivl_scope_port(def, idx);
draw_send_function_argument(port);
}
/* Call the function */
+7 -7
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2013-2014 Stephen Williams (steve@icarus.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
@@ -643,16 +643,16 @@ static void draw_binary_vec4_lrs(ivl_expr_t expr)
// the stack and replace it with the result of the shift.
switch (ivl_expr_opcode(expr)) {
case 'l': /* << */
fprintf(vvp_out, " %%shiftl %u;\n", use_index_reg);
fprintf(vvp_out, " %%shiftl %d;\n", use_index_reg);
break;
case 'r': /* >> */
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
fprintf(vvp_out, " %%shiftr %d;\n", use_index_reg);
break;
case 'R': /* >>> */
if (ivl_expr_signed(le))
fprintf(vvp_out, " %%shiftr/s %u;\n", use_index_reg);
fprintf(vvp_out, " %%shiftr/s %d;\n", use_index_reg);
else
fprintf(vvp_out, " %%shiftr %u;\n", use_index_reg);
fprintf(vvp_out, " %%shiftr %d;\n", use_index_reg);
break;
default:
assert(0);
@@ -790,10 +790,10 @@ static void draw_concat_number_vec4(ivl_expr_t expr, int as_concati)
if (accum) {
if (count_pushi) {
fprintf(vvp_out, " %%concati/vec4 %lu, %lu, %u;\n",
fprintf(vvp_out, " %%concati/vec4 %lu, %lu, %d;\n",
val0, valx, accum);
} else {
fprintf(vvp_out, " %%pushi/vec4 %lu, %lu, %u;\n",
fprintf(vvp_out, " %%pushi/vec4 %lu, %lu, %d;\n",
val0, valx, accum);
}
}
+7 -7
View File
@@ -143,7 +143,7 @@ static void get_vec_from_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice
draw_eval_vec4(part_off_ex);
fprintf(vvp_out, " %%flag_mov %u, 4;\n", slice->u_.part_select_dynamic.x_flag);
fprintf(vvp_out, " %%dup/vec4;\n");
fprintf(vvp_out, " %%ix/vec4 %u;\n", slice->u_.part_select_dynamic.word_idx_reg);
fprintf(vvp_out, " %%ix/vec4 %d;\n", slice->u_.part_select_dynamic.word_idx_reg);
fprintf(vvp_out, " %%part/u %u;\n", wid);
} else if (ivl_signal_dimensions(sig) > 0 && word_ix == 0) {
@@ -167,7 +167,7 @@ static void get_vec_from_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice
slice->u_.memory_word_dynamic.x_flag = allocate_flag();
draw_eval_expr_into_integer(word_ix, slice->u_.memory_word_dynamic.word_idx_reg);
fprintf(vvp_out, " %%flag_mov %d, 4;\n", slice->u_.memory_word_dynamic.x_flag);
fprintf(vvp_out, " %%flag_mov %u, 4;\n", slice->u_.memory_word_dynamic.x_flag);
fprintf(vvp_out, " %%load/vec4a v%p, %d;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
} else {
@@ -263,7 +263,7 @@ static void put_vec_to_lval_slice(ivl_lval_t lval, struct vec_slice_info*slice,
break;
case SLICE_MEMORY_WORD_DYNAMIC:
fprintf(vvp_out, " %%flag_mov 4, %d;\n", slice->u_.memory_word_dynamic.x_flag);
fprintf(vvp_out, " %%flag_mov 4, %u;\n", slice->u_.memory_word_dynamic.x_flag);
fprintf(vvp_out, " %%store/vec4a v%p, %d, 0;\n", sig, slice->u_.memory_word_dynamic.word_idx_reg);
clr_word(slice->u_.memory_word_dynamic.word_idx_reg);
clr_flag(slice->u_.memory_word_dynamic.x_flag);
@@ -381,7 +381,7 @@ static void store_vec4_to_lval(ivl_statement_t net)
/* Note that flag4 is set by the eval above. */
assert(lsig);
if (ivl_signal_type(lsig)==IVL_SIT_UWIRE) {
fprintf(vvp_out, " %%force/vec4/off v%p_0, %u;\n",
fprintf(vvp_out, " %%force/vec4/off v%p_0, %d;\n",
lsig, offset_index);
} else {
fprintf(vvp_out, " %%store/vec4 v%p_0, %d, %u;\n",
@@ -397,7 +397,7 @@ static void store_vec4_to_lval(ivl_statement_t net)
assert(!lsig);
ivl_type_t sub_type = draw_lval_expr(nest);
assert(ivl_type_base(sub_type) == IVL_VT_CLASS);
fprintf(vvp_out, " %%store/prop/v %u, %u;\n",
fprintf(vvp_out, " %%store/prop/v %d, %u;\n",
ivl_lval_property_idx(lval), lwid);
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
@@ -449,6 +449,7 @@ static int show_stmt_assign_vector(ivl_statement_t net)
fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_string_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
ivl_expr_signal(rval), ivl_lval_sig(lval));
if (slices) free(slices);
return 0;
} else {
@@ -532,8 +533,7 @@ static int show_stmt_assign_vector(ivl_statement_t net)
break;
}
if (slices)
free(slices);
if (slices) free(slices);
return 0;
}
+5 -2
View File
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2011 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-2014 Stephen Williams (steve@icarus.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
@@ -59,7 +59,10 @@ __inline__ static void draw_execute_header(ivl_design_t des)
{
const char*cp = ivl_design_flag(des, "VVP_EXECUTABLE");
if (cp) {
fprintf(vvp_out, "#! %s\n", cp);
const char *extra_args = ivl_design_flag(des, "VVP_EXTRA_ARGS");
if (!extra_args)
extra_args = "";
fprintf(vvp_out, "#! %s%s\n", cp, extra_args);
#if !defined(__MINGW32__)
fchmod(fileno(vvp_out), 0755);
#endif
+25 -13
View File
@@ -114,14 +114,12 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
ivl_expr_t part_off_ex,
unsigned nevents)
{
unsigned skip_assign = transient_id++;
int word_ix_reg = 3;
int part_off_reg = 0;
int delay_index;
unsigned long part_off = 0;
int error_flag = allocate_flag();
fprintf(vvp_out, " %%flag_set/imm %d, 0;\n", error_flag);
/* Figure the constant part offset, if possible. If we can do
so, then forget about the expression and use the calculated
@@ -143,11 +141,13 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
/* Calculate array word index into word index register */
draw_eval_expr_into_integer(word_ix, word_ix_reg);
fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag);
if (part_off_ex) {
part_off_reg = allocate_word();
/* Save the index calculation error flag to a global. */
fprintf(vvp_out, " %%flag_mov %d, 4;\n", error_flag);
draw_eval_expr_into_integer(part_off_ex, part_off_reg);
/* Add the error state of the part select to the global. */
fprintf(vvp_out, " %%flag_or %d, 4;\n", error_flag);
} else if (part_off != 0) {
@@ -158,26 +158,35 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
part_off_reg, part_off);
}
/* Calculated delay... */
if (dexp != 0) {
/* Calculated delay... */
delay_index = allocate_word();
/* If needed save the index calculation error flag. */
if (! part_off_ex) {
fprintf(vvp_out, " %%flag_mov %d, 4;\n", error_flag);
}
draw_eval_expr_into_integer(dexp, delay_index);
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
if (word_ix_reg != 3) {
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg);
clr_word(word_ix_reg);
}
/* Restore the error state since an undefined delay is okay. */
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %d;\n",
lsig, part_off_reg, delay_index);
clr_word(delay_index);
/* Event control delay... */
} else if (nevents != 0) {
/* Event control delay... */
/* If needed use the global error state. */
if (part_off_ex) {
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
}
fprintf(vvp_out, " %%assign/vec4/a/e v%p, %d;\n", lsig, part_off_reg);
/* Constant delay... */
} else {
/* Constant delay... */
unsigned long low_d = delay % UINT64_C(0x100000000);
unsigned long hig_d = delay / UINT64_C(0x100000000);
@@ -185,15 +194,18 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix,
fprintf(vvp_out, " %%ix/load %d, %lu, %lu; Constant delay\n",
delay_index, low_d, hig_d);
if (word_ix_reg != 3) {
fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg);
fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg);
clr_word(word_ix_reg);
}
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %u;\n",
/* If needed use the global error state. */
if (part_off_ex) {
fprintf(vvp_out, " %%flag_mov 4, %d;\n", error_flag);
}
fprintf(vvp_out, " %%assign/vec4/a/d v%p, %d, %d;\n",
lsig, part_off_reg, delay_index);
clr_word(delay_index);
}
fprintf(vvp_out, "t_%u ;\n", skip_assign);
if (nevents != 0) fprintf(vvp_out, " %%evctl/c;\n");
clr_flag(error_flag);
@@ -1321,7 +1333,7 @@ static int show_stmt_do_while(ivl_statement_t net, ivl_scope_t sscope)
the result. If the expression evaluates to true, then
branch to the top label. */
int use_flag = draw_eval_condition(ivl_stmt_cond_expr(net));
fprintf(vvp_out, " %%jmp/1 T_%u.%u, %u;\n",
fprintf(vvp_out, " %%jmp/1 T_%u.%u, %d;\n",
thread_count, top_label, use_flag);
clr_flag(use_flag);
@@ -1665,7 +1677,7 @@ static int show_stmt_while(ivl_statement_t net, ivl_scope_t sscope)
the result. If the expression evaluates to false, then
branch to the out label. */
int use_flag = draw_eval_condition(ivl_stmt_cond_expr(net));
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, %u;\n",
fprintf(vvp_out, " %%jmp/0xz T_%u.%u, %d;\n",
thread_count, out_label, use_flag);
clr_flag(use_flag);
+1 -1
View File
@@ -1,6 +1,6 @@
#norootforbuild
#
%define rev_date 20141205
%define rev_date 20150105
# Normally, the suff-ix is %nil, meaning the suffix is to not be used.
# But if the builder wants to make a suffixed package, he may set this
# to a value (i.e. -test) to cause suffixes to be put in all the right
+3 -1
View File
@@ -780,7 +780,9 @@ ostream& operator<< (ostream&o, const verinum&v)
/* If the number is fully defined (no x or z) then print it
out as a decimal number. */
if (v.is_defined() && v.len() <= 8*sizeof(long)) {
unsigned dec_len = 8*sizeof(int); /* avoid 32/64 bit differences. */
if (! v.has_sign()) dec_len -= 1; /* an unsigned number. */
if (v.is_defined() && v.len() <= dec_len) {
if (v.has_sign())
o << "'sd" << v.as_long();
else
+23
View File
@@ -108,6 +108,7 @@ static string make_library_package_path(perm_string lib_name, perm_string name)
static void import_ieee(void);
static void import_ieee_use(ActiveScope*res, perm_string package, perm_string name);
static void import_std_use(const YYLTYPE&loc, ActiveScope*res, perm_string package, perm_string name);
static void dump_library_package(ostream&file, perm_string lname, perm_string pname, Package*pack)
{
@@ -211,6 +212,9 @@ void library_import(const YYLTYPE&loc, const std::list<perm_string>*names)
// The ieee library is special and handled by an
// internal function.
import_ieee();
} else if (*cur == "std") {
// The std library is always implicitly imported.
} else if (*cur == "work") {
// The work library is always implicitly imported.
@@ -238,6 +242,11 @@ void library_use(const YYLTYPE&loc, ActiveScope*res,
import_ieee_use(res, use_package, use_name);
return;
}
// Special case handling for the STD library.
if (use_library == "std") {
import_std_use(loc, res, use_package, use_name);
return;
}
struct library_contents&lib = libraries[use_library];
Package*pack = lib.packages[use_package];
@@ -361,6 +370,20 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na
}
}
static void import_std_use(const YYLTYPE&loc, ActiveScope*/*res*/, perm_string package, perm_string name)
{
if (package == "standard") {
// do nothing
return;
} else if (package == "textio") {
cerr << "warning: textio package not really supported" << endl;
return;
} else {
sorrymsg(loc, "package %s of library %s not yet supported", package.str(), name.str());
return;
}
}
const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true);
const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true);
const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER);
+27 -27
View File
@@ -232,59 +232,59 @@ unusedFunction:fastlz.c:150
// lz4.c from GTKWave
// These functions are not used by Icarus
// LZ4_compress_continue()
unusedFunction:lz4.c:819
unusedFunction:lz4.c:883
// LZ4_compress_forceExtDict()
unusedFunction:lz4.c:831
unusedFunction:lz4.c:895
// LZ4_compress_limitedOutput()
unusedFunction:lz4.c:666
unusedFunction:lz4.c:730
// LZ4_compress_limitedOutput_continue()
unusedFunction:lz4.c:824
unusedFunction:lz4.c:888
// LZ4_compress_limitedOutput_withState()
unusedFunction:lz4.c:1273
unusedFunction:lz4.c:1343
// LZ4_compress_withState()
unusedFunction:lz4.c:1262
unusedFunction:lz4.c:1332
// LZ4_create()
unusedFunction:lz4.c:1242
unusedFunction:lz4.c:1314
// LZ4_createStream()
unusedFunction:lz4.c:701
unusedFunction:lz4.c:765
// LZ4_createStreamDecode()
unusedFunction:lz4.c:1080
unusedFunction:lz4.c:1152
// LZ4_decompress_fast_continue()
unusedFunction:lz4.c:1145
unusedFunction:lz4.c:1217
// LZ4_decompress_fast_usingDict()
unusedFunction:lz4.c:1200
unusedFunction:lz4.c:1272
// LZ4_decompress_fast_withPrefix64k()
unusedFunction:lz4.c:1291
unusedFunction:lz4.c:1361
// LZ4_decompress_safe_continue()
unusedFunction:lz4.c:1116
unusedFunction:lz4.c:1188
// LZ4_decompress_safe_forceExtDict()
unusedFunction:lz4.c:1206
unusedFunction:lz4.c:1278
// LZ4_decompress_safe_usingDict()
unusedFunction:lz4.c:1195
unusedFunction:lz4.c:1267
// LZ4_decompress_safe_withPrefix64k()
unusedFunction:lz4.c:1286
unusedFunction:lz4.c:1356
// LZ4_freeStream()
unusedFunction:lz4.c:709
unusedFunction:lz4.c:773
// LZ4_freeStreamDecode()
unusedFunction:lz4.c:1086
unusedFunction:lz4.c:1158
// LZ4_loadDict()
unusedFunction:lz4.c:716
unusedFunction:lz4.c:780
// LZ4_resetStreamState()
unusedFunction:lz4.c:1235
unusedFunction:lz4.c:1307
// LZ4_setStreamDecode()
unusedFunction:lz4.c:1099
unusedFunction:lz4.c:1171
// LZ4_sizeofState()
unusedFunction:lz4.c:1260
unusedFunction:lz4.c:1330
// LZ4_sizeofStreamState()
unusedFunction:lz4.c:1227
unusedFunction:lz4.c:1299
// LZ4_slideInputBuffer()
unusedFunction:lz4.c:1249
unusedFunction:lz4.c:1321
// LZ4_uncompress()
unusedFunction:lz4.c:1221
unusedFunction:lz4.c:1293
// LZ4_uncompress_unknownOutputSize()
unusedFunction:lz4.c:1222
unusedFunction:lz4.c:1294
// LZ4_versionNumber()
unusedFunction:lz4.c:372
unusedFunction:lz4.c:428
// The routines in sys_random.c are exact copies from IEEE1364-2005 and
// they have scope warnings that we need to ignore.
+365 -292
View File
@@ -1,6 +1,6 @@
/*
LZ4 - Fast LZ compression algorithm
Copyright (C) 2011-2014, Yann Collet.
Copyright (C) 2011-2015, Yann Collet.
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
Redistribution and use in source and binary forms, with or without
@@ -27,86 +27,78 @@
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
You can contact the author at :
- LZ4 source repository : http://code.google.com/p/lz4/
- LZ4 source repository : http://code.google.com/p/lz4
- LZ4 source mirror : https://github.com/Cyan4973/lz4
- LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c
*/
/**************************************
Tuning parameters
**************************************/
/*
* HEAPMODE :
* Select how default compression functions will allocate memory for their hash table,
* in memory stack (0:default, fastest), or in memory heap (1:requires memory allocation (malloc)).
* in memory stack (0:default, fastest), or in memory heap (1:requires malloc()).
*/
#define HEAPMODE 0
/*
* CPU_HAS_EFFICIENT_UNALIGNED_MEMORY_ACCESS :
* By default, the source code expects the compiler to correctly optimize
* 4-bytes and 8-bytes read on architectures able to handle it efficiently.
* This is not always the case. In some circumstances (ARM notably),
* the compiler will issue cautious code even when target is able to correctly handle unaligned memory accesses.
*
* You can force the compiler to use unaligned memory access by uncommenting the line below.
* One of the below scenarios will happen :
* 1 - Your target CPU correctly handle unaligned access, and was not well optimized by compiler (good case).
* You will witness large performance improvements (+50% and up).
* Keep the line uncommented and send a word to upstream (https://groups.google.com/forum/#!forum/lz4c)
* The goal is to automatically detect such situations by adding your target CPU within an exception list.
* 2 - Your target CPU correctly handle unaligned access, and was already already optimized by compiler
* No change will be experienced.
* 3 - Your target CPU inefficiently handle unaligned access.
* You will experience a performance loss. Comment back the line.
* 4 - Your target CPU does not handle unaligned access.
* Program will crash.
* If uncommenting results in better performance (case 1)
* please report your configuration to upstream (https://groups.google.com/forum/#!forum/lz4c)
* An automatic detection macro will be added to match your case within future versions of the library.
*/
/* #define CPU_HAS_EFFICIENT_UNALIGNED_MEMORY_ACCESS 1 */
/**************************************
CPU Feature Detection
**************************************/
/* 32 or 64 bits ? */
#if (defined(__x86_64__) || defined(_M_X64) || defined(_WIN64) \
|| defined(__64BIT__) || defined(__mips64) \
|| defined(__powerpc64__) || defined(__powerpc64le__) \
|| defined(__ppc64__) || defined(__ppc64le__) \
|| defined(__PPC64__) || defined(__PPC64LE__) \
|| defined(__ia64) || defined(__itanium__) || defined(_M_IA64) \
|| defined(__s390x__) ) /* Detects 64 bits mode */
# define LZ4_ARCH64 1
#else
# define LZ4_ARCH64 0
#endif
#define LZ4_32BITS (sizeof(void*)==4)
#define LZ4_64BITS (sizeof(void*)==8)
/*
* Little Endian or Big Endian ?
* Overwrite the #define below if you know your architecture endianess
* Automated efficient unaligned memory access detection
* Based on known hardware architectures
* This list will be updated thanks to feedbacks
*/
#include <stdlib.h> /* Apparently required to detect endianess */
#if defined (__GLIBC__)
# include <endian.h>
# if (__BYTE_ORDER == __BIG_ENDIAN)
# define LZ4_BIG_ENDIAN 1
# endif
#elif (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN))
# define LZ4_BIG_ENDIAN 1
#elif defined(__sparc) || defined(__sparc__) \
|| defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) \
|| defined(__hpux) || defined(__hppa) \
|| defined(_MIPSEB) || defined(__s390__)
# define LZ4_BIG_ENDIAN 1
#if defined(CPU_HAS_EFFICIENT_UNALIGNED_MEMORY_ACCESS) \
|| defined(__ARM_FEATURE_UNALIGNED) \
|| defined(__i386__) || defined(__x86_64__) \
|| defined(_M_IX86) || defined(_M_X64) \
|| defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_8__) \
|| (defined(_M_ARM) && (_M_ARM >= 7))
# define LZ4_UNALIGNED_ACCESS 1
#else
/* Little Endian assumed. PDP Endian and other very rare endian format are unsupported. */
# define LZ4_UNALIGNED_ACCESS 0
#endif
/*
* Unaligned memory access is automatically enabled for "common" CPU, such as x86.
* For others CPU, such as ARM, the compiler may be more cautious, inserting unnecessary extra code to ensure aligned access property
* If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance
* LZ4_FORCE_SW_BITCOUNT
* Define this parameter if your target system or compiler does not support hardware bit count
*/
#if defined(__ARM_FEATURE_UNALIGNED)
# define LZ4_FORCE_UNALIGNED_ACCESS 1
#endif
/* Define this parameter if your target system or compiler does not support hardware bit count */
#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */
# define LZ4_FORCE_SW_BITCOUNT
#endif
/*
* BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE :
* This option may provide a small boost to performance for some big endian cpu, although probably modest.
* You may set this option to 1 if data will remain within closed environment.
* This option is useless on Little_Endian CPU (such as x86)
*/
/* #define BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE 1 */
/**************************************
Compiler Options
Compiler Options
**************************************/
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
/* "restrict" is a known keyword */
@@ -116,28 +108,20 @@
#ifdef _MSC_VER /* Visual Studio */
# define FORCE_INLINE static __forceinline
# include <intrin.h> /* For Visual 2005 */
# if LZ4_ARCH64 /* 64-bits */
# pragma intrinsic(_BitScanForward64) /* For Visual 2005 */
# pragma intrinsic(_BitScanReverse64) /* For Visual 2005 */
# else /* 32-bits */
# pragma intrinsic(_BitScanForward) /* For Visual 2005 */
# pragma intrinsic(_BitScanReverse) /* For Visual 2005 */
# endif
# include <intrin.h>
# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */
# pragma warning(disable : 4293) /* disable: C4293: too large shift (32-bits) */
#else
# ifdef __GNUC__
# define FORCE_INLINE static inline __attribute__((always_inline))
# if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */
# ifdef __GNUC__
# define FORCE_INLINE static inline __attribute__((always_inline))
# else
# define FORCE_INLINE static inline
# endif
# else
# define FORCE_INLINE static inline
# endif
#endif
#ifdef _MSC_VER /* Visual Studio */
# define lz4_bswap16(x) _byteswap_ushort(x)
#else
# define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8)))
#endif
# define FORCE_INLINE static
# endif /* __STDC_VERSION__ */
#endif /* _MSC_VER */
#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
@@ -185,46 +169,132 @@
typedef unsigned long long U64;
#endif
#if defined(__GNUC__) && !defined(LZ4_FORCE_UNALIGNED_ACCESS)
# define _PACKED __attribute__ ((packed))
#else
# define _PACKED
/**************************************
Reading and writing into memory
**************************************/
#define STEPSIZE sizeof(size_t)
static unsigned LZ4_64bits(void) { return sizeof(void*)==8; }
static unsigned LZ4_isLittleEndian(void)
{
const union { U32 i; BYTE c[4]; } one = { 1 }; /* don't use static : performance detrimental */
return one.c[0];
}
static U16 LZ4_readLE16(const void* memPtr)
{
if ((LZ4_UNALIGNED_ACCESS) && (LZ4_isLittleEndian()))
return *(U16*)memPtr;
else
{
const BYTE* p = memPtr;
return (U16)((U16)p[0] + (p[1]<<8));
}
}
static void LZ4_writeLE16(void* memPtr, U16 value)
{
if ((LZ4_UNALIGNED_ACCESS) && (LZ4_isLittleEndian()))
{
*(U16*)memPtr = value;
return;
}
else
{
BYTE* p = memPtr;
p[0] = (BYTE) value;
p[1] = (BYTE)(value>>8);
}
}
static U16 LZ4_read16(const void* memPtr)
{
if (LZ4_UNALIGNED_ACCESS)
return *(U16*)memPtr;
else
{
U16 val16;
memcpy(&val16, memPtr, 2);
return val16;
}
}
static U32 LZ4_read32(const void* memPtr)
{
if (LZ4_UNALIGNED_ACCESS)
return *(U32*)memPtr;
else
{
U32 val32;
memcpy(&val32, memPtr, 4);
return val32;
}
}
static U64 LZ4_read64(const void* memPtr)
{
if (LZ4_UNALIGNED_ACCESS)
return *(U64*)memPtr;
else
{
U64 val64;
memcpy(&val64, memPtr, 8);
return val64;
}
}
static size_t LZ4_read_ARCH(const void* p)
{
if (LZ4_64bits())
return (size_t)LZ4_read64(p);
else
return (size_t)LZ4_read32(p);
}
static void LZ4_copy4(void* dstPtr, const void* srcPtr)
{
if (LZ4_UNALIGNED_ACCESS)
{
*(U32*)dstPtr = *(U32*)srcPtr;
return;
}
memcpy(dstPtr, srcPtr, 4);
}
static void LZ4_copy8(void* dstPtr, const void* srcPtr)
{
#if GCC_VERSION!=409 /* disabled on GCC 4.9, as it generates invalid opcode (crash) */
if (LZ4_UNALIGNED_ACCESS)
{
if (LZ4_64bits())
*(U64*)dstPtr = *(U64*)srcPtr;
else
((U32*)dstPtr)[0] = ((U32*)srcPtr)[0],
((U32*)dstPtr)[1] = ((U32*)srcPtr)[1];
return;
}
#endif
memcpy(dstPtr, srcPtr, 8);
}
#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__)
# if defined(__IBMC__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
# pragma pack(1)
# else
# pragma pack(push, 1)
# endif
#endif
typedef struct { U16 v; } _PACKED U16_S;
typedef struct { U32 v; } _PACKED U32_S;
typedef struct { U64 v; } _PACKED U64_S;
typedef struct {size_t v;} _PACKED size_t_S;
#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__)
# if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
# pragma pack(0)
# else
# pragma pack(pop)
# endif
#endif
#define A16(x) (((U16_S *)(x))->v)
#define A32(x) (((U32_S *)(x))->v)
#define A64(x) (((U64_S *)(x))->v)
#define AARCH(x) (((size_t_S *)(x))->v)
/* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */
static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd)
{
BYTE* d = dstPtr;
const BYTE* s = srcPtr;
BYTE* e = dstEnd;
do { LZ4_copy8(d,s); d+=8; s+=8; } while (d<e);
}
/**************************************
Constants
Common Constants
**************************************/
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
#define HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
#define HASH_SIZE_U32 (1 << LZ4_HASHLOG)
#define MINMATCH 4
#define COPYLENGTH 8
@@ -232,13 +302,10 @@ typedef struct {size_t v;} _PACKED size_t_S;
#define MFLIMIT (COPYLENGTH+MINMATCH)
static const int LZ4_minLength = (MFLIMIT+1);
#define KB *(1U<<10)
#define MB *(1U<<20)
#define KB *(1 <<10)
#define MB *(1 <<20)
#define GB *(1U<<30)
#define LZ4_64KLIMIT ((64 KB) + (MFLIMIT-1))
#define SKIPSTRENGTH 6 /* Increasing this value will make the compression run slower on incompressible data */
#define MAXD_LOG 16
#define MAX_DISTANCE ((1 << MAXD_LOG) - 1)
@@ -249,15 +316,129 @@ static const int LZ4_minLength = (MFLIMIT+1);
/**************************************
Structures and local types
Common Utils
**************************************/
#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
/********************************
Common functions
********************************/
static unsigned LZ4_NbCommonBytes (register size_t val)
{
if (LZ4_isLittleEndian())
{
if (LZ4_64bits())
{
# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
unsigned long r = 0;
_BitScanForward64( &r, (U64)val );
return (int)(r>>3);
# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
return (__builtin_ctzll((U64)val) >> 3);
# else
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
# endif
}
else /* 32 bits */
{
# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
unsigned long r;
_BitScanForward( &r, (U32)val );
return (int)(r>>3);
# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
return (__builtin_ctz((U32)val) >> 3);
# else
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
# endif
}
}
else /* Big Endian CPU */
{
if (LZ4_64bits())
{
# if defined(_MSC_VER) && defined(_WIN64) && !defined(LZ4_FORCE_SW_BITCOUNT)
unsigned long r = 0;
_BitScanReverse64( &r, val );
return (unsigned)(r>>3);
# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
return (__builtin_clzll(val) >> 3);
# else
unsigned r;
if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
r += (!val);
return r;
# endif
}
else /* 32 bits */
{
# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
unsigned long r = 0;
_BitScanReverse( &r, (unsigned long)val );
return (unsigned)(r>>3);
# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
return (__builtin_clz(val) >> 3);
# else
unsigned r;
if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
r += (!val);
return r;
# endif
}
}
}
static unsigned LZ4_count(const BYTE* pIn, const BYTE* pMatch, const BYTE* pInLimit)
{
const BYTE* const pStart = pIn;
while (likely(pIn<pInLimit-(STEPSIZE-1)))
{
size_t diff = LZ4_read_ARCH(pMatch) ^ LZ4_read_ARCH(pIn);
if (!diff) { pIn+=STEPSIZE; pMatch+=STEPSIZE; continue; }
pIn += LZ4_NbCommonBytes(diff);
return (unsigned)(pIn - pStart);
}
if (LZ4_64bits()) if ((pIn<(pInLimit-3)) && (LZ4_read32(pMatch) == LZ4_read32(pIn))) { pIn+=4; pMatch+=4; }
if ((pIn<(pInLimit-1)) && (LZ4_read16(pMatch) == LZ4_read16(pIn))) { pIn+=2; pMatch+=2; }
if ((pIn<pInLimit) && (*pMatch == *pIn)) pIn++;
return (unsigned)(pIn - pStart);
}
#ifndef LZ4_COMMONDEFS_ONLY
/**************************************
Local Constants
**************************************/
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
#define HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
#define HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
static const int LZ4_64Klimit = ((64 KB) + (MFLIMIT-1));
static const U32 LZ4_skipTrigger = 6; /* Increase this value ==> compression run slower on incompressible data */
/**************************************
Local Utils
**************************************/
int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); }
/**************************************
Local Structures and types
**************************************/
typedef struct {
U32 hashTable[HASH_SIZE_U32];
U32 currentOffset;
U32 initCheck;
U32 hashTable[HASH_SIZE_U32];
U32 currentOffset;
U32 initCheck;
const BYTE* dictionary;
const BYTE* bufferStart;
U32 dictSize;
U32 dictSize;
} LZ4_stream_t_internal;
typedef enum { notLimited = 0, limitedOutput = 1 } limitedOutput_directive;
@@ -270,109 +451,12 @@ typedef enum { endOnOutputSize = 0, endOnInputSize = 1 } endCondition_directive;
typedef enum { full = 0, partial = 1 } earlyEnd_directive;
/**************************************
Architecture-specific macros
**************************************/
#define STEPSIZE sizeof(size_t)
#define LZ4_COPYSTEP(d,s) { AARCH(d) = AARCH(s); d+=STEPSIZE; s+=STEPSIZE; }
#define LZ4_COPY8(d,s) { LZ4_COPYSTEP(d,s); if (STEPSIZE<8) LZ4_COPYSTEP(d,s); }
#if (defined(LZ4_BIG_ENDIAN) && !defined(BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE))
# define LZ4_READ_LITTLEENDIAN_16(d,s,p) { U16 v = A16(p); v = lz4_bswap16(v); d = (s) - v; }
# define LZ4_WRITE_LITTLEENDIAN_16(p,i) { U16 v = (U16)(i); v = lz4_bswap16(v); A16(p) = v; p+=2; }
#else /* Little Endian */
# define LZ4_READ_LITTLEENDIAN_16(d,s,p) { d = (s) - A16(p); }
# define LZ4_WRITE_LITTLEENDIAN_16(p,v) { A16(p) = v; p+=2; }
#endif
/**************************************
Macros
**************************************/
#define LZ4_STATIC_ASSERT(c) { enum { LZ4_static_assert = 1/(int)(!!(c)) }; } /* use only *after* variable declarations */
#if LZ4_ARCH64 || !defined(__GNUC__)
# define LZ4_WILDCOPY(d,s,e) { do { LZ4_COPY8(d,s) } while (d<e); } /* at the end, d>=e; */
#else
# define LZ4_WILDCOPY(d,s,e) { if (likely(e-d <= 8)) LZ4_COPY8(d,s) else do { LZ4_COPY8(d,s) } while (d<e); }
#endif
/****************************
Private local functions
****************************/
#if LZ4_ARCH64
static int LZ4_NbCommonBytes (register U64 val)
{
# if defined(LZ4_BIG_ENDIAN)
# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
unsigned long r = 0;
_BitScanReverse64( &r, val );
return (int)(r>>3);
# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
return (__builtin_clzll(val) >> 3);
# else
int r;
if (!(val>>32)) { r=4; } else { r=0; val>>=32; }
if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; }
r += (!val);
return r;
# endif
# else
# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
unsigned long r = 0;
_BitScanForward64( &r, val );
return (int)(r>>3);
# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
return (__builtin_ctzll(val) >> 3);
# else
static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 };
return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58];
# endif
# endif
}
#else
static int LZ4_NbCommonBytes (register U32 val)
{
# if defined(LZ4_BIG_ENDIAN)
# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
unsigned long r = 0;
_BitScanReverse( &r, val );
return (int)(r>>3);
# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
return (__builtin_clz(val) >> 3);
# else
int r;
if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; }
r += (!val);
return r;
# endif
# else
# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT)
unsigned long r;
_BitScanForward( &r, val );
return (int)(r>>3);
# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT)
return (__builtin_ctz(val) >> 3);
# else
static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 };
return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27];
# endif
# endif
}
#endif
/********************************
Compression functions
********************************/
int LZ4_versionNumber (void) { return LZ4_VERSION_NUMBER; }
int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); }
static int LZ4_hashSequence(U32 sequence, tableType_t tableType)
static U32 LZ4_hashSequence(U32 sequence, tableType_t tableType)
{
if (tableType == byU16)
return (((sequence) * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1)));
@@ -380,15 +464,15 @@ static int LZ4_hashSequence(U32 sequence, tableType_t tableType)
return (((sequence) * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG));
}
static int LZ4_hashPosition(const BYTE* p, tableType_t tableType) { return LZ4_hashSequence(A32(p), tableType); }
static U32 LZ4_hashPosition(const BYTE* p, tableType_t tableType) { return LZ4_hashSequence(LZ4_read32(p), tableType); }
static void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase)
{
switch (tableType)
{
case byPtr: { const BYTE** hashTable = (const BYTE**) tableBase; hashTable[h] = p; break; }
case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); break; }
case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); break; }
case byPtr: { const BYTE** hashTable = (const BYTE**)tableBase; hashTable[h] = p; return; }
case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); return; }
case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); return; }
}
}
@@ -411,32 +495,12 @@ static const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t t
return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase);
}
static unsigned LZ4_count(const BYTE* pIn, const BYTE* pRef, const BYTE* pInLimit)
{
const BYTE* const pStart = pIn;
while (likely(pIn<pInLimit-(STEPSIZE-1)))
{
size_t diff = AARCH(pRef) ^ AARCH(pIn);
if (!diff) { pIn+=STEPSIZE; pRef+=STEPSIZE; continue; }
pIn += LZ4_NbCommonBytes(diff);
return (unsigned)(pIn - pStart);
}
if (LZ4_64BITS) if ((pIn<(pInLimit-3)) && (A32(pRef) == A32(pIn))) { pIn+=4; pRef+=4; }
if ((pIn<(pInLimit-1)) && (A16(pRef) == A16(pIn))) { pIn+=2; pRef+=2; }
if ((pIn<pInLimit) && (*pRef == *pIn)) pIn++;
return (unsigned)(pIn - pStart);
}
static int LZ4_compress_generic(
void* ctx,
const char* source,
char* dest,
int inputSize,
int maxOutputSize,
limitedOutput_directive outputLimited,
tableType_t tableType,
dict_directive dict,
@@ -459,7 +523,6 @@ static int LZ4_compress_generic(
BYTE* op = (BYTE*) dest;
BYTE* const olimit = op + maxOutputSize;
const int skipStrength = SKIPSTRENGTH;
U32 forwardH;
size_t refDelta=0;
@@ -481,8 +544,8 @@ static int LZ4_compress_generic(
lowLimit = (const BYTE*)source;
break;
}
if ((tableType == byU16) && (inputSize>=(int)LZ4_64KLIMIT)) return 0; /* Size too large (not within 64K limit) */
if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
if ((tableType == byU16) && (inputSize>=LZ4_64Klimit)) return 0; /* Size too large (not within 64K limit) */
if (inputSize<LZ4_minLength) goto _last_literals; /* Input too small, no compression (all literals) */
/* First Byte */
LZ4_putPosition(ip, ctx, tableType, base);
@@ -491,26 +554,26 @@ static int LZ4_compress_generic(
/* Main Loop */
for ( ; ; )
{
const BYTE* ref;
const BYTE* match;
BYTE* token;
{
const BYTE* forwardIp = ip;
unsigned step=1;
unsigned searchMatchNb = (1U << skipStrength);
unsigned searchMatchNb = (1U << LZ4_skipTrigger);
/* Find a match */
do {
U32 h = forwardH;
ip = forwardIp;
forwardIp += step;
step = searchMatchNb++ >> skipStrength;
step = searchMatchNb++ >> LZ4_skipTrigger;
if (unlikely(forwardIp > mflimit)) goto _last_literals;
ref = LZ4_getPositionOnHash(h, ctx, tableType, base);
match = LZ4_getPositionOnHash(h, ctx, tableType, base);
if (dict==usingExtDict)
{
if (ref<(const BYTE*)source)
if (match<(const BYTE*)source)
{
refDelta = dictDelta;
lowLimit = dictionary;
@@ -524,13 +587,13 @@ static int LZ4_compress_generic(
forwardH = LZ4_hashPosition(forwardIp, tableType);
LZ4_putPositionOnHash(ip, h, ctx, tableType, base);
} while ( ((dictIssue==dictSmall) ? (ref < lowRefLimit) : 0)
|| ((tableType==byU16) ? 0 : (ref + MAX_DISTANCE < ip))
|| (A32(ref+refDelta) != A32(ip)) );
} while ( ((dictIssue==dictSmall) ? (match < lowRefLimit) : 0)
|| ((tableType==byU16) ? 0 : (match + MAX_DISTANCE < ip))
|| (LZ4_read32(match+refDelta) != LZ4_read32(ip)) );
}
/* Catch up */
while ((ip>anchor) && (ref+refDelta > lowLimit) && (unlikely(ip[-1]==ref[refDelta-1]))) { ip--; ref--; }
while ((ip>anchor) && (match+refDelta > lowLimit) && (unlikely(ip[-1]==match[refDelta-1]))) { ip--; match--; }
{
/* Encode Literal length */
@@ -548,12 +611,13 @@ static int LZ4_compress_generic(
else *token = (BYTE)(litLength<<ML_BITS);
/* Copy Literals */
{ BYTE* end = op+litLength; LZ4_WILDCOPY(op,anchor,end); op=end; }
LZ4_wildCopy(op, anchor, op+litLength);
op+=litLength;
}
_next_match:
/* Encode Offset */
LZ4_WRITE_LITTLEENDIAN_16(op, (U16)(ip-ref));
LZ4_writeLE16(op, (U16)(ip-match)); op+=2;
/* Encode MatchLength */
{
@@ -562,10 +626,10 @@ _next_match:
if ((dict==usingExtDict) && (lowLimit==dictionary))
{
const BYTE* limit;
ref += refDelta;
limit = ip + (dictEnd-ref);
match += refDelta;
limit = ip + (dictEnd-match);
if (limit > matchlimit) limit = matchlimit;
matchLength = LZ4_count(ip+MINMATCH, ref+MINMATCH, limit);
matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, limit);
ip += MINMATCH + matchLength;
if (ip==limit)
{
@@ -576,14 +640,14 @@ _next_match:
}
else
{
matchLength = LZ4_count(ip+MINMATCH, ref+MINMATCH, matchlimit);
matchLength = LZ4_count(ip+MINMATCH, match+MINMATCH, matchlimit);
ip += MINMATCH + matchLength;
}
if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit)))
return 0; /* Check output limit */
if (matchLength>=ML_MASK)
{
if ((outputLimited) && (unlikely(op + (1 + LASTLITERALS) + (matchLength>>8) > olimit)))
return 0; /* Check output limit */
*token += ML_MASK;
matchLength -= ML_MASK;
for (; matchLength >= 510 ; matchLength-=510) { *op++ = 255; *op++ = 255; }
@@ -602,10 +666,10 @@ _next_match:
LZ4_putPosition(ip-2, ctx, tableType, base);
/* Test next position */
ref = LZ4_getPosition(ip, ctx, tableType, base);
match = LZ4_getPosition(ip, ctx, tableType, base);
if (dict==usingExtDict)
{
if (ref<(const BYTE*)source)
if (match<(const BYTE*)source)
{
refDelta = dictDelta;
lowLimit = dictionary;
@@ -617,9 +681,9 @@ _next_match:
}
}
LZ4_putPosition(ip, ctx, tableType, base);
if ( ((dictIssue==dictSmall) ? (ref>=lowRefLimit) : 1)
&& (ref+MAX_DISTANCE>=ip)
&& (A32(ref+refDelta)==A32(ip)) )
if ( ((dictIssue==dictSmall) ? (match>=lowRefLimit) : 1)
&& (match+MAX_DISTANCE>=ip)
&& (LZ4_read32(match+refDelta)==LZ4_read32(ip)) )
{ token=op++; *token=0; goto _next_match; }
/* Prepare next loop */
@@ -646,16 +710,16 @@ _last_literals:
int LZ4_compress(const char* source, char* dest, int inputSize)
{
#if (HEAPMODE)
void* ctx = ALLOCATOR(LZ4_STREAMSIZE_U32, 4); /* Aligned on 4-bytes boundaries */
void* ctx = ALLOCATOR(LZ4_STREAMSIZE_U64, 8); /* Aligned on 8-bytes boundaries */
#else
U32 ctx[LZ4_STREAMSIZE_U32] = {0}; /* Ensure data is aligned on 4-bytes boundaries */
U64 ctx[LZ4_STREAMSIZE_U64] = {0}; /* Ensure data is aligned on 8-bytes boundaries */
#endif
int result;
if (inputSize < (int)LZ4_64KLIMIT)
if (inputSize < LZ4_64Klimit)
result = LZ4_compress_generic((void*)ctx, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue);
else
result = LZ4_compress_generic((void*)ctx, source, dest, inputSize, 0, notLimited, LZ4_64BITS ? byU32 : byPtr, noDict, noDictIssue);
result = LZ4_compress_generic((void*)ctx, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue);
#if (HEAPMODE)
FREEMEM(ctx);
@@ -666,16 +730,16 @@ int LZ4_compress(const char* source, char* dest, int inputSize)
int LZ4_compress_limitedOutput(const char* source, char* dest, int inputSize, int maxOutputSize)
{
#if (HEAPMODE)
void* ctx = ALLOCATOR(LZ4_STREAMSIZE_U32, 4); /* Aligned on 4-bytes boundaries */
void* ctx = ALLOCATOR(LZ4_STREAMSIZE_U64, 8); /* Aligned on 8-bytes boundaries */
#else
U32 ctx[LZ4_STREAMSIZE_U32] = {0}; /* Ensure data is aligned on 4-bytes boundaries */
U64 ctx[LZ4_STREAMSIZE_U64] = {0}; /* Ensure data is aligned on 8-bytes boundaries */
#endif
int result;
if (inputSize < (int)LZ4_64KLIMIT)
if (inputSize < LZ4_64Klimit)
result = LZ4_compress_generic((void*)ctx, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue);
else
result = LZ4_compress_generic((void*)ctx, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64BITS ? byU32 : byPtr, noDict, noDictIssue);
result = LZ4_compress_generic((void*)ctx, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue);
#if (HEAPMODE)
FREEMEM(ctx);
@@ -700,7 +764,7 @@ void LZ4_resetStream (LZ4_stream_t* LZ4_stream)
LZ4_stream_t* LZ4_createStream(void)
{
LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOCATOR(4, LZ4_STREAMSIZE_U32);
LZ4_stream_t* lz4s = (LZ4_stream_t*)ALLOCATOR(8, LZ4_STREAMSIZE_U64);
LZ4_STATIC_ASSERT(LZ4_STREAMSIZE >= sizeof(LZ4_stream_t_internal)); /* A compilation error here means LZ4_STREAMSIZE is not large enough */
LZ4_resetStream(lz4s);
return lz4s;
@@ -956,14 +1020,16 @@ FORCE_INLINE int LZ4_decompress_generic(
op += length;
break; /* Necessarily EOF, due to parsing restrictions */
}
LZ4_WILDCOPY(op, ip, cpy); ip -= (op-cpy); op = cpy;
LZ4_wildCopy(op, ip, cpy);
ip += length; op = cpy;
/* get offset */
LZ4_READ_LITTLEENDIAN_16(match,cpy,ip); ip+=2;
match = cpy - LZ4_readLE16(ip); ip+=2;
if ((checkOffset) && (unlikely(match < lowLimit))) goto _output_error; /* Error : offset outside destination buffer */
/* get matchlength */
if ((length=(token&ML_MASK)) == ML_MASK)
length = token & ML_MASK;
if (length == ML_MASK)
{
unsigned s;
do
@@ -1012,7 +1078,7 @@ FORCE_INLINE int LZ4_decompress_generic(
/* copy repeated sequence */
cpy = op + length;
if (unlikely((op-match)<(int)STEPSIZE))
if (unlikely((op-match)<8))
{
const size_t dec64 = dec64table[op-match];
op[0] = match[0];
@@ -1020,17 +1086,23 @@ FORCE_INLINE int LZ4_decompress_generic(
op[2] = match[2];
op[3] = match[3];
match += dec32table[op-match];
A32(op+4) = A32(match);
LZ4_copy4(op+4, match);
op += 8; match -= dec64;
} else { LZ4_COPY8(op,match); }
} else { LZ4_copy8(op, match); op+=8; match+=8; }
if (unlikely(cpy>oend-12))
{
if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last 5 bytes must be literals */
if (op<oend-COPYLENGTH) LZ4_WILDCOPY(op, match, (oend-COPYLENGTH));
while(op<cpy) *op++=*match++;
if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last LASTLITERALS bytes must be literals */
if (op < oend-8)
{
LZ4_wildCopy(op, match, oend-8);
match += (oend-8) - op;
op = oend-8;
}
while (op<cpy) *op++ = *match++;
}
else LZ4_WILDCOPY(op, match, cpy);
else
LZ4_wildCopy(op, match, cpy);
op=cpy; /* correction */
}
@@ -1079,7 +1151,7 @@ typedef struct
*/
LZ4_streamDecode_t* LZ4_createStreamDecode(void)
{
LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOCATOR(sizeof(U32), LZ4_STREAMDECODESIZE_U32);
LZ4_streamDecode_t* lz4s = (LZ4_streamDecode_t*) ALLOCATOR(sizeof(U64), LZ4_STREAMDECODESIZE_U64);
return lz4s;
}
@@ -1241,18 +1313,16 @@ int LZ4_resetStreamState(void* state, const char* inputBuffer)
void* LZ4_create (const char* inputBuffer)
{
void* lz4ds = ALLOCATOR(4, LZ4_STREAMSIZE_U32);
void* lz4ds = ALLOCATOR(8, LZ4_STREAMSIZE_U64);
LZ4_init ((LZ4_stream_t_internal*)lz4ds, (const BYTE*)inputBuffer);
return lz4ds;
}
char* LZ4_slideInputBuffer (void* LZ4_Data)
{
LZ4_stream_t_internal* lz4ds = (LZ4_stream_t_internal*)LZ4_Data;
LZ4_saveDict((LZ4_stream_t*)LZ4_Data, (char*)lz4ds->bufferStart, 64 KB);
return (char*)(lz4ds->bufferStart + 64 KB);
LZ4_stream_t_internal* ctx = (LZ4_stream_t_internal*)LZ4_Data;
int dictSize = LZ4_saveDict((LZ4_stream_t*)ctx, (char*)ctx->bufferStart, 64 KB);
return (char*)(ctx->bufferStart + dictSize);
}
/* Obsolete compresson functions using User-allocated state */
@@ -1264,10 +1334,10 @@ int LZ4_compress_withState (void* state, const char* source, char* dest, int inp
if (((size_t)(state)&3) != 0) return 0; /* Error : state is not aligned on 4-bytes boundary */
MEM_INIT(state, 0, LZ4_STREAMSIZE);
if (inputSize < (int)LZ4_64KLIMIT)
if (inputSize < LZ4_64Klimit)
return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, byU16, noDict, noDictIssue);
else
return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64BITS ? byU32 : byPtr, noDict, noDictIssue);
return LZ4_compress_generic(state, source, dest, inputSize, 0, notLimited, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue);
}
int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize)
@@ -1275,10 +1345,10 @@ int LZ4_compress_limitedOutput_withState (void* state, const char* source, char*
if (((size_t)(state)&3) != 0) return 0; /* Error : state is not aligned on 4-bytes boundary */
MEM_INIT(state, 0, LZ4_STREAMSIZE);
if (inputSize < (int)LZ4_64KLIMIT)
if (inputSize < LZ4_64Klimit)
return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, byU16, noDict, noDictIssue);
else
return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64BITS ? byU32 : byPtr, noDict, noDictIssue);
return LZ4_compress_generic(state, source, dest, inputSize, maxOutputSize, limitedOutput, LZ4_64bits() ? byU32 : byPtr, noDict, noDictIssue);
}
/* Obsolete streaming decompression functions */
@@ -1292,3 +1362,6 @@ int LZ4_decompress_fast_withPrefix64k(const char* source, char* dest, int origin
{
return LZ4_decompress_generic(source, dest, 0, originalSize, endOnOutputSize, full, 0, withPrefix64k, (BYTE*)dest - 64 KB, NULL, 64 KB);
}
#endif /* LZ4_COMMONDEFS_ONLY */
+21 -29
View File
@@ -46,8 +46,8 @@ extern "C" {
/**************************************
Version
**************************************/
#define LZ4_VERSION_MAJOR 1 /* for major interface/format changes */
#define LZ4_VERSION_MINOR 4 /* for minor interface/format changes */
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
#define LZ4_VERSION_MINOR 5 /* for new (non-breaking) interface capabilities */
#define LZ4_VERSION_RELEASE 0 /* for tweaks, bug-fixes, or development */
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
int LZ4_versionNumber (void);
@@ -169,17 +169,19 @@ int LZ4_decompress_safe_partial (const char* source, char* dest, int compressedS
/***********************************************
Experimental Streaming Compression Functions
Streaming Compression Functions
***********************************************/
#define LZ4_STREAMSIZE_U32 ((1 << (LZ4_MEMORY_USAGE-2)) + 8)
#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U32 * sizeof(unsigned int))
#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4)
#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(long long))
/*
* LZ4_stream_t
* information structure to track an LZ4 stream.
* important : init this structure content before first use !
* note : only allocated directly the structure if you are statically linking LZ4
* If you are using liblz4 as a DLL, please use below construction methods instead.
*/
typedef struct { unsigned int table[LZ4_STREAMSIZE_U32]; } LZ4_stream_t;
typedef struct { long long table[LZ4_STREAMSIZE_U64]; } LZ4_stream_t;
/*
* LZ4_resetStream
@@ -188,9 +190,10 @@ typedef struct { unsigned int table[LZ4_STREAMSIZE_U32]; } LZ4_stream_t;
void LZ4_resetStream (LZ4_stream_t* LZ4_streamPtr);
/*
* If you prefer dynamic allocation methods,
* LZ4_createStream will allocate and initialize an LZ4_stream_t structure
* LZ4_freeStream releases its memory.
* In the context of a DLL (liblz4), please use these methods rather than the static struct.
* They are more future proof, in case of a change of LZ4_stream_t size.
*/
LZ4_stream_t* LZ4_createStream(void);
int LZ4_freeStream (LZ4_stream_t* LZ4_streamPtr);
@@ -231,20 +234,19 @@ int LZ4_saveDict (LZ4_stream_t* LZ4_streamPtr, char* safeBuffer, int dictSize);
/************************************************
Experimental Streaming Decompression Functions
Streaming Decompression Functions
************************************************/
#define LZ4_STREAMDECODESIZE_U32 8
#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U32 * sizeof(unsigned int))
#define LZ4_STREAMDECODESIZE_U64 4
#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
typedef struct { unsigned long long table[LZ4_STREAMDECODESIZE_U64]; } LZ4_streamDecode_t;
/*
* LZ4_streamDecode_t
* information structure to track an LZ4 stream.
* important : init this structure content using LZ4_setStreamDecode or memset() before first use !
*/
typedef struct { unsigned int table[LZ4_STREAMDECODESIZE_U32]; } LZ4_streamDecode_t;
/*
* If you prefer dynamic allocation methods,
* init this structure content using LZ4_setStreamDecode or memset() before first use !
*
* In the context of a DLL (liblz4) please prefer usage of construction methods below.
* They are more future proof, in case of a change of LZ4_streamDecode_t size in the future.
* LZ4_createStreamDecode will allocate and initialize an LZ4_streamDecode_t structure
* LZ4_freeStreamDecode releases its memory.
*/
@@ -254,9 +256,7 @@ int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
/*
* LZ4_setStreamDecode
* Use this function to instruct where to find the dictionary.
* This function can be used to specify a static dictionary,
* or to instruct where to find some previously decoded data saved into a different memory space.
* Setting a size of 0 is allowed (same effect as no dictionary, same effect as reset).
* Setting a size of 0 is allowed (same effect as reset).
* Return : 1 if OK, 0 if error
*/
int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
@@ -277,7 +277,7 @@ Advanced decoding functions :
*_usingDict() :
These decoding functions work the same as
a combination of LZ4_setDictDecode() followed by LZ4_decompress_x_continue()
They don't use nor update an LZ4_streamDecode_t structure.
They are stand-alone and don't use nor update an LZ4_streamDecode_t structure.
*/
int LZ4_decompress_safe_usingDict (const char* source, char* dest, int compressedSize, int maxDecompressedSize, const char* dictStart, int dictSize);
int LZ4_decompress_fast_usingDict (const char* source, char* dest, int originalSize, const char* dictStart, int dictSize);
@@ -294,18 +294,10 @@ They are only provided here for compatibility with older user programs.
- LZ4_uncompress is the same as LZ4_decompress_fast
- LZ4_uncompress_unknownOutputSize is the same as LZ4_decompress_safe
These function prototypes are now disabled; uncomment them if you really need them.
It is highly recommended to stop using these functions and migrated to newer ones */
It is highly recommended to stop using these functions and migrate to newer ones */
/* int LZ4_uncompress (const char* source, char* dest, int outputSize); */
/* int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize); */
/*
* If you prefer dynamic allocation methods,
* LZ4_createStreamDecode()
* provides a pointer (void*) towards an initialized LZ4_streamDecode_t structure.
* LZ4_free just frees it.
*/
/* void* LZ4_createStreamDecode(void); */
/*int LZ4_free (void* LZ4_stream); yes, it's the same one as for compression */
/* Obsolete streaming functions; use new streaming interface whenever possible */
void* LZ4_create (const char* inputBuffer);
+55 -16
View File
@@ -1,12 +1,49 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
; Copyright (c) 2001-2014 Stephen Williams ([email protected])
;
; This example demonstrates a simple blocking assignment to a
; reg vector within a module.
; This program is free software; you can redistribute it and/or modify
; it 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
;
; This example demonstrates a simple non-blocking assignment to a
; reg vector within a module. It is similar to the code that the
; following Verilog program would generate:
;
; module main;
;
; reg [7:0] test;
;
; initial begin
; test <= #2 0;
; #3 $display("test = %b", test);
;
; test <= #2 1;
; #1 $display("test = %b", test);
; #2 $display("test = %b", test);
;
; test <= #2 2;
; #3 $display("test = %b", test);
;
; test <= #2 3;
; #3 $display("test = %b", test);
; end
;
; endmodule
main .scope module, "main" "main";
main .scope module, "main" "main" 0 0;
; This declares a "reg" data type named "test" in the current scope.
; The bit range is given for the purposes of VPI access. The range
@@ -14,28 +51,30 @@ main .scope module, "main" "main";
; bit wide vector.
test .var "test", 7 0;
; The %assign/v0 opcode assigns a vector to the .var at the label,
; with the given delay. The width of the vector from index register0.
; The %assign/vec4 opcode assigns a vector to the .var at the label,
; with the given absolute delay.
T0 %ix/load 0, 8 ; Set the width of the vector to 8.
%assign/v0 test, 2, 0 ;
T0 %pushi/vec4 0, 0, 8;
%assign/vec4 test, 2;
%delay 3, 0;
%vpi_call 0 0 "$display", "test = %b", test;
%vpi_call 0 0 "$display", "test = %b", test {0 0 0};
%assign/v0 test, 2, 1 ;
%pushi/vec4 1, 0, 8;
%assign/vec4 test, 2;
%delay 1, 0;
%vpi_call 0 0 "$display", "test = %b", test;
%vpi_call 0 0 "$display", "test = %b", test {0 0 0};
%delay 2, 0;
%vpi_call 0 0 "$display", "test = %b", test;
%vpi_call 0 0 "$display", "test = %b", test {0 0 0};
%assign/v0 test, 2, 2 ;
%pushi/vec4 2, 0, 8;
%assign/vec4 test, 2;
%delay 3, 0;
%vpi_call 0 0 "$display", "test = %b", test;
%vpi_call 0 0 "$display", "test = %b", test {0 0 0};
%assign/v0 test, 2, 3 ;
%pushi/vec4 3, 0, 8;
%assign/vec4 test, 2;
%delay 3, 0;
%vpi_call 0 0 "$display", "test = %b", test;
%vpi_call 0 0 "$display", "test = %b", test {0 0 0};
%end;
.thread T0;
+18 -17
View File
@@ -1,25 +1,24 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
; Copyright (c) 2001-2008 Stephen Williams ([email protected])
; Copyright (c) 2001-2014 Stephen Williams ([email protected])
;
; 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 free software; you can redistribute it and/or modify
; it 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
; 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; This example is similar to the code that the following Verilog program
; would make:
; would generate:
;
; module main;
; reg a;
@@ -36,18 +35,20 @@
; properly. This is a very trivial functor propagation that is initiated
; by the %set instruction.
main .scope module, "main";
main .scope module, "main" "main" 0 0;
V_main.a .var "a", 0 0;
V_main.b .net "b", 0 0, V_main.a;
code
%set/v V_main.a, 0, 1;
code %pushi/vec4 0, 0, 1;
%store/vec4 V_main.a, 0, 1;
%delay 1, 0;
%vpi_call 0 0 "$display", "a=%b, b=%b", V_main.a, V_main.b;
%set/v V_main.a, 1, 1;
%vpi_call 0 0 "$display", "a=%b, b=%b", V_main.a, V_main.b {0 0 0};
%pushi/vec4 1, 0, 1;
%store/vec4 V_main.a, 0, 1;
%delay 1, 0;
%vpi_call 0 0 "$display", "a=%b, b=%b", V_main.a, V_main.b;
%vpi_call 0 0 "$display", "a=%b, b=%b", V_main.a, V_main.b {0 0 0};
%end;
.thread code;
+23 -23
View File
@@ -1,21 +1,21 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
; Copyright (c) 2001-2008 Stephen Williams ([email protected])
; Copyright (c) 2001-2014 Stephen Williams ([email protected])
;
; 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 free software; you can redistribute it and/or modify
; it 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
; 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; This example is similar to the following Verilog code. The idea is
@@ -26,24 +26,24 @@
;
; module main;
; task test;
; begin
; #5 $display("FAILED...");
; $finish;
; end
; begin
; #5 $display("FAILED...");
; $finish;
; end
; endtask
;
; initial begin
; fork
; test;
; #1 disable test;
; join
; $display("PASSED");
; fork
; test;
; #1 disable test;
; join
; $display("PASSED");
; end
; endmodule
;
S_main .scope module, "main";
S_test .scope task, "test", S_main;
S_main .scope module, "main" "main" 0 0;
S_test .scope task, "test" "test" 0 0, 0 0 0, S_main;
; This code in the implementation of the thread that goes into the
@@ -52,8 +52,8 @@ S_test .scope task, "test", S_main;
.scope S_test;
T_0/1 ;
%delay 5, 0;
%vpi_call 0 0 "$display", "FAILED -- thread wasn't disabled";
%vpi_call 0 0 "$finish";
%vpi_call 0 0 "$display", "FAILED -- thread wasn't disabled" {0 0 0};
%vpi_call 0 0 "$finish" {0 0 0};
%end;
; This is the main thread. Fork the thread under test, delay for a
@@ -68,7 +68,7 @@ T_0 ;
%disable S_test ; This is the statement that I'm testing.
%join;
%vpi_call 0 0 "$display", "PASSED";
%vpi_call 0 0 "$display", "PASSED" {0 0 0};
%end;
.thread T_0;
+20 -20
View File
@@ -1,53 +1,53 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
; Copyright (c) 2001-2008 Stephen Williams ([email protected])
; Copyright (c) 2001-2014 Stephen Williams ([email protected])
;
; 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 free software; you can redistribute it and/or modify
; it 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
; 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; This example tests the operation of a simple posedge event. The module
; that would generate code like this would be:
;
; module main;
; reg a;
; reg a;
;
; initial begin
; initial begin
; a = 0;
; #1 a = 1;
; end
; end
;
; always @(posedge a) $display("Got a posedge.");
; always @(posedge a) $display("Got a posedge.");
;
; endmodule
;
main .scope module, "main";
main .scope module, "main" "main" 0 0;
V_main.a .var "a", 0 0;
V_main.b .event posedge, V_main.a;
code
%set/v V_main.a, 0, 1;
code %pushi/vec4 0, 0, 1;
%store/vec4 V_main.a, 0, 1;
%delay 1, 0;
%set/v V_main.a, 1, 1;
%pushi/vec4 1, 0, 1;
%store/vec4 V_main.a, 0, 1;
%end;
.thread code;
loop %wait V_main.b;
%vpi_call 0 0 "$display", "Got a posedge.";
%vpi_call 0 0 "$display", "Got a posedge." {0 0 0};
%jmp loop;
.thread loop;
:file_names 2;
+14 -13
View File
@@ -1,33 +1,34 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
; Copyright (c) 2001-2008 Stephen Williams ([email protected])
; Copyright (c) 2001-2014 Stephen Williams ([email protected])
;
; 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 free software; you can redistribute it and/or modify
; it 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
; 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; This sample demonstrates the behavior of %fork and %join.
S_main .scope module, "main";
child %vpi_call 0 0 "$display", "I'm a child";
S_main .scope module, "main" "main" 0 0;
child %vpi_call 0 0 "$display", "I'm a child" {0 0 0};
%end;
parent %fork child, S_main;
%vpi_call 0 0 "$display", "I'm a parent";
%vpi_call 0 0 "$display", "I'm a parent" {0 0 0};
%join;
%vpi_call 0 0 "$display", "reaped";
%vpi_call 0 0 "$display", "Reaped child" {0 0 0};
%end;
.thread parent;
+14 -14
View File
@@ -1,37 +1,37 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
; Copyright (c) 2001-2008 Stephen Williams ([email protected])
; Copyright (c) 2001-2014 Stephen Williams ([email protected])
;
; 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 free software; you can redistribute it and/or modify
; it 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
; 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; This example is similar to the code that the following Verilog program
; would make:
; would generate:
;
; module main;
; initial $display("Hello, World.");
; endmodule
;
; This tests that a simple %vpi_call works properly. This is very nearly
; the mode trivial VVP source file that can generate any output.
; the most trivial VVP source file that can generate any output.
main .scope module, "main";
code
%vpi_call 0 0 "$display", "Hello, World." {0 0};
main .scope module, "main" "main" 0 0;
code %vpi_call 0 0 "$display", "Hello, World." {0 0 0};
%end;
.thread code;
:file_names 2;
+19 -19
View File
@@ -1,32 +1,32 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
; Copyright (c) 2001-2008 Stephen Williams ([email protected])
; Copyright (c) 2001-2014 Stephen Williams ([email protected])
;
; 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 free software; you can redistribute it and/or modify
; it 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
; 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; This example slightly extends the hello.vvp example by adding the
; set and display of a reg variable. The Verilog source that would
; make this might be:
;
; module main;
; reg [3:0] value1;
; initial begin
; value1 = 1;
; $display("value = %b", value1);
; end
; reg [3:0] value1;
; initial begin
; value1 = 1;
; $display("value = %b", value1);
; end
; endmodule
;
; Notice that the var "value1" is placed into the "main" scope simply
@@ -34,14 +34,15 @@
; notice that the Vmain.value1 label is automatically converted to a
; vpiHandle by the compiler when the %vpi_call statement is compiled.
Smain .scope module, "main";
Smain .scope module, "main" "main" 0 0;
Vmain.value1 .var "value1", 3 0;
T00 %movi 8, 1, 4; Load a 4 bit value (1) into location 8.
%set/v Vmain.value1, 8, 4;
T00 %pushi/vec4 1, 0, 4; Push a 4 bit value (1) on the stack
%store/vec4 Vmain.value1, 0, 4;
%vpi_call 0 0 "$display", "value = %b", Vmain.value1;
%vpi_call 0 0 "$display", "value = %b", Vmain.value1 {0 0 0};
%end;
@@ -49,4 +50,3 @@ T00 %movi 8, 1, 4; Load a 4 bit value (1) into location 8.
:file_names 2;
"N/A";
"<interactive>";
+212 -132
View File
@@ -1,40 +1,33 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
; IMPORTANT NOTE:
;
; This example uses constructs that are no longer supported. It will
; not run with the current vvp implementation!
; Copyright (c) 2001-2008 Stephen Williams ([email protected])
; Copyright (c) 2001-2014 Stephen Williams ([email protected])
; Copyright (c) 2001 Stephan Boettcher <[email protected]>
;
; 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 free software; you can redistribute it and/or modify
; it 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
; 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; This sample demonstrates memory, also including index register
; arithmetic. And a memory write port
main .scope "example";
main .scope module, "example" "example" 0 0;
;;; Make a memory.
;
; reg [8:2] memory[5:27];
memory .mem "memory", 8,2, 27,5 ;
memory .array "memory", 27 5, 8 2;
;;; The word width is 7 bits [8:2].
;;; The memory size is 23 words, 5..27.
@@ -49,42 +42,159 @@ memory .mem "memory", 8,2, 27,5 ;
; wire [5:0] d = memory[a][8:3];
; reg [6:0] m;
a .var "a", 4,0;
we .var "we", 0,0;
a .var "a", 4 0;
we .var "we", 0 0;
wclk .event "wclk";
di .var "di", 5,0;
d .net "d", 5,0, mem[0],mem[1],mem[2],mem[3],mem[4],mem[5];
mem .mem/port memory, 6,1,
5, a[0],a[1],a[2],a[3],a[4],
wclk, we, di[0],di[1],di[2],di[3],di[4],di[5];
m .var "m", 6,0;
di .var "di", 5 0;
d .net "d", 5 0, m_part;
mem_prt .array/port memory, mem_idx;
; The memory index is normalized (a-5) using one extra bit to allow negative
; (wrapped) values to be out of range.
mem_idx .arith/sub 6, a_pad, C4<000101>;
a_pad .concat [5 1 0 0], a, C4<0>;
; Select 6 bits from the memory port starting at the second bit.
m_part .part mem_prt, 1, 6;
m .var "m", 6 0;
;;; The data port mem[] does not connect to the LSB of the memory.
;;; Initialize some part of the memory. Starting at memory bit [20],
;;; which is in the middle of the third memory word, memory[7]. The
;;; memory words occupy 8 bits each, that is 7 rounded up to the next
;;; multiple of 4.
;;; Initialize the last part of the memory. Starting at the middle of the
;;; the third memory word, memory[7] bit 6.
;
; initial begin
; memory[7][8:6] = 8'h55;
; memory[8] = 8'h00;
; memory[9] = 8'h00;
; memory[10] = 8'h50;
; memory[11] = 8'h05;
; memory[12] = 8'h05;
; memory[13] = 8'h50;
; memory[14] = 8'h05;
; memory[15] = 8'h05;
; memory[16] = 8'h00;
; memory[17] = 8'h00;
; memory[18] = 8'h00;
; memory[19] = 8'h01;
; memory[20] = 8'h00;
; memory[21] = 8'h04;
; memory[22] = 8'h00;
; memory[23] = 8'h10;
; memory[24] = 8'h00;
; memory[25] = 8'h40;
; memory[26] = 8'h01;
; memory[27] = 8'h00;
; end
;;; Four bits per byte. Word fill bits are included. Commas are
;;; optional, there may be a comma after the last byte.
.scope main;
mem_init ;
%pushi/vec4 5, 0, 3; value to store
%ix/load 4, 2, 0; word index (7 -> zero based)
%ix/load 5, 4, 0; bit index (6 -> zero based)
%flag_set/imm 4, 0; the index values are defined
%store/vec4a memory, 4, 5;
.mem/init memory[20],
0x55
0x00 0x00
0x50 0x05
0x05 0x50
0x05 0x05
0x00 0x00
0x00 0x01
0x00 0x04
0x00 0x10
0x00 0x40
0x01 0x00
0x04,0x00,
0x10,0x00,
0x40,0x00,
;
%pushi/vec4 0, 0, 7; value to store
%ix/load 4, 3, 0; word index (8 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 0, 0, 7; value to store
%ix/load 4, 4, 0; word index (9 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 80, 0, 7; value to store
%ix/load 4, 5, 0; word index (10 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 5, 0, 7; value to store
%ix/load 4, 6, 0; word index (11 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 5, 0, 7; value to store
%ix/load 4, 7, 0; word index (12 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 80, 0, 7; value to store
%ix/load 4, 8, 0; word index (13 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 5, 0, 7; value to store
%ix/load 4, 9, 0; word index (14 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 5, 0, 7; value to store
%ix/load 4, 10, 0; word index (15 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 0, 0, 7; value to store
%ix/load 4, 11, 0; word index (16 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 0, 0, 7; value to store
%ix/load 4, 12, 0; word index (17 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 0, 0, 7; value to store
%ix/load 4, 13, 0; word index (18 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 1, 0, 7; value to store
%ix/load 4, 14, 0; word index (19 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 0, 0, 7; value to store
%ix/load 4, 15, 0; word index (20 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 4, 0, 7; value to store
%ix/load 4, 16, 0; word index (21 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 0, 0, 7; value to store
%ix/load 4, 17, 0; word index (22 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 16, 0, 7; value to store
%ix/load 4, 18, 0; word index (23 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 0, 0, 7; value to store
%ix/load 4, 19, 0; word index (24 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 64, 0, 7; value to store
%ix/load 4, 20, 0; word index (25 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 1, 0, 7; value to store
%ix/load 4, 21, 0; word index (26 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%pushi/vec4 0, 0, 7; value to store
%ix/load 4, 22, 0; word index (27 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%store/vec4a memory, 4, 0;
%end;
.thread mem_init;
;;; Run through the addresses and display the data output.
;
@@ -97,33 +207,23 @@ m .var "m", 6,0;
.scope main;
always ;
%delay 5;
%delay 5, 0;
%vpi_call "$display", "a:%b d:%b", a, d;
%vpi_call 0 0 "$display", "a:%b d:%b", a, d {0 0 0};
%set wclk, 0;
%event wclk;
%delay 5;
%delay 5, 0;
%load 10, a[0];
%load 11, a[1];
%load 12, a[2];
%load 13, a[3];
%load 14, a[4];
%mov 20, 1, 1;
%mov 21, 0, 4;
%add 10, 20, 5;
%assign a[0], 0, 10;
%assign a[1], 0, 11;
%assign a[2], 0, 12;
%assign a[3], 0, 13;
%assign a[4], 0, 14;
%load/vec4 a;
%addi 1, 0, 5;
%assign/vec4 a, 0;
%jmp always;
.thread always;
;;; Initialize a[], run some cycles, overwrite a memory word, run a
;;; bit more, read a memory word, finish.
;;; Initialize the variables, run some cycles, overwrite a memory word, run
;;; a bit more, read a memory word, finish.
;
; initial
; begin
@@ -149,78 +249,58 @@ always ;
.scope main;
initial ;
%set we, 0;
%set di[0], 0;
%set di[1], 1;
%set di[2], 2;
%set di[3], 3;
%set di[4], 0;
%set di[5], 1;
%set a[0], 0;
%set a[1], 0;
%set a[2], 0;
%set a[3], 0;
%set a[4], 0;
%pushi/vec4 0, 0, 1;
%store/vec4 we, 0, 1;
%delay 220;
%vpi_call "$readmemh", "memory.hex", memory;
%delay 30;
%set we, 1;
%delay 5;
%vpi_call "$display", "write to a=%b", a;
%delay 5;
%set we, 0;
%delay 60;
%pushi/vec4 38, 12, 6;
%store/vec4 di, 0, 6;
%pushi/vec4 0, 0, 5;
%store/vec4 a, 0, 5;
%delay 220, 0;
%vpi_call 0 0 "$readmemh", "memory.hex", memory {0 0 0};
%delay 30, 0;
%pushi/vec4 1, 0, 1;
%store/vec4 we, 0, 1;
%delay 5, 0;
%vpi_call 0 0 "$display", "write to a=%b", a {0 0 0};
%delay 5, 0;
%pushi/vec4 0, 0, 1;
%store/vec4 we, 0, 1;
%delay 60, 0;
;;; Memories are indexed by index register 3. The index register
;;; points to the bit position in the memory. Each memory word
;;; occupies a multiple of 4 bits. Bit position zero is the LSB of
;;; the first memory word, here: memory[5][2].
;;; points to the zero based word position in the memory.
%ix/load 3, 23 ; memory word index
%ix/sub 3, 5 ; minus memory root index
%ix/mul 3, 8 ; times memory word size (rounded up)
%assign/m memory, 0, 1;
%ix/add 3, 1 ; next bit
%assign/m memory, 0, 0;
%ix/add 3, 1 ;
%assign/m memory, 0, 3;
%ix/add 3, 1 ;
%assign/m memory, 0, 2;
%ix/add 3, 1 ;
%assign/m memory, 0, 1;
%ix/add 3, 1 ;
%assign/m memory, 0, 0;
%ix/add 3, 1 ;
%assign/m memory, 0, 0;
%pushi/vec4 25, 12, 7;
%ix/load 3, 18, 0; memory word index (23 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%assign/vec4/a/d memory, 0, 0;
%delay 320;
%delay 320, 0;
%ix/load 3, 32 ; precomputed memory bit index
%load/m 10, memory;
%set m[0], 10;
%ix/add 3, 1 ;
%load/m 10, memory;
%set m[1], 10;
%ix/add 3, 1 ;
%load/m 10, memory;
%set m[2], 10;
%ix/add 3, 1 ;
%load/m 10, memory;
%set m[3], 10;
%ix/add 3, 1 ;
%load/m 10, memory;
%set m[4], 10;
%ix/add 3, 1 ;
%load/m 10, memory;
%set m[5], 10;
%ix/add 3, 1 ;
%load/m 10, memory;
%set m[6], 10;
%vpi_call "$display", "memory[9]=%b", m;
%ix/load 4, 4, 0; memory word index (9 -> zero based)
%flag_set/imm 4, 0; the index value is defined
%load/vec4a memory, 4;
%store/vec4 m, 0, 7;
#1;
%vpi_call "$finish";
%vpi_call 0 0 "$display", "memory[9]=%b", m {0 0 0};
%delay 1, 0;
%vpi_call 0 0 "$finish" {0 0 0};
%end;
.thread initial;
:file_names 2;
"N/A";
"<interactive>";
+51 -14
View File
@@ -1,35 +1,72 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
; Copyright (c) 2001-2014 Stephen Williams ([email protected])
;
; This program is free software; you can redistribute it and/or modify
; it 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; This example is similar to the code that the following Verilog program
; would generate:
;
; module main;
; reg [7:0] test;
;
; initial begin
; test = 8'h00;
; $display("test = %b", test);
; test = 8'hff;
; $display("test = %b", test);
; test = 8'hzz;
; $display("test = %b", test);
; test = 8'hxx;
; $display("test = %b", test);
; end
; endmodule
;
; This example demonstrates a simple blocking assignment to a
; reg vector within a module.
;
main .scope module, "main" "main";
main .scope module, "main" "main" 0 0;
; This declares a "reg" data type named "test" in the current scope.
; The bit range is given for the purposes of VPI access. The range
; corresponds to the declaration "reg [7:0] test", so leads to an 8
; bit wide vector.
test .var "test", 7 0;
; The %set/v opcode writes a value to the target .var vector. The
; first operand is the label of the .var object. The second and
; third operands are the base and width of the bit set that is to
; be made into the vector to write.
; Push various 8 bit values to the stack, save them to the variable and
; then print the value of the variable.
T0 %set/v test, 0, 8 ;
%vpi_call 0 0 "$display", "test = %b", test;
T0 %pushi/vec4 0, 0, 8; Push 8 bits of 0
%store/vec4 test, 0, 8;
%vpi_call 0 0 "$display", "test = %b", test {0 0 0};
%set/v test, 1, 8 ;
%vpi_call 0 0 "$display", "test = %b", test;
%pushi/vec4 255, 0, 8; Push 8 bits of 1
%store/vec4 test, 0, 8;
%vpi_call 0 0 "$display", "test = %b", test {0 0 0};
%set/v test, 2, 8 ;
%vpi_call 0 0 "$display", "test = %b", test;
%pushi/vec4 0, 255, 8; Push 8 bits of z
%store/vec4 test, 0, 8;
%vpi_call 0 0 "$display", "test = %b", test {0 0 0};
%set/v test, 3, 8 ;
%vpi_call 0 0 "$display", "test = %b", test;
%pushi/vec4 255, 255, 8; Push 8 bits of x
%store/vec4 test, 0, 8;
%vpi_call 0 0 "$display", "test = %b", test {0 0 0};
%end;
.thread T0;
+25 -25
View File
@@ -1,34 +1,35 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
; Copyright (c) 2001-2008 Stephen Williams ([email protected])
; Copyright (c) 2001-2014 Stephen Williams ([email protected])
;
; 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 free software; you can redistribute it and/or modify
; it 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
; 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; This example shows how to wire up a simple adder. The code below is
; like what might be generated from the Verilog:
; This example shows how to wire a simple adder. The code below is like what
; would be generated from the following Verilog program:
;
; module main;
; reg [3:0] A, B;
; wire [3:0] Q = A + B;
; reg [3:0] A, B;
; wire [3:0] Q = A + B;
;
; initial begin
; A = 2;
; B = 3;
; #1 $display("%b %b = %b", A, B, Q);
; end
; initial begin
; A = 2;
; B = 3;
; #1 $display("%b + %b = %b", A, B, Q);
; end
; endmodule
;
; Notice the use of the .arith/sum statement, including the specification
@@ -36,7 +37,7 @@
; passed to the statement.
S_main .scope module, "main";
S_main .scope module, "main" "main" 0 0;
A .var "A", 3 0;
B .var "B", 3 0;
@@ -44,15 +45,14 @@ Q .net "Q", 3 0, add;
add .arith/sum 4, A, B;
start %movi 8, 2, 4; Load a 4 bit value (2) into location 8
%set/v A, 8, 4;
%movi 8, 3, 4; Ditto except the value is 3
%set/v B, 8, 4;
start %pushi/vec4 2, 0, 4; Push a 4 bit value (2) on the stack
%store/vec4 A, 0, 4;
%pushi/vec4 3, 0, 4; Ditto except the value is 3
%store/vec4 B, 0, 4;
%delay 1, 0;
%vpi_call 0 0 "$display", "%b + %b == %b", A, B, Q;
%vpi_call 0 0 "$display", "%b + %b == %b", A, B, Q {0 0 0};
%end;
.thread start;
:file_names 2;
+14 -14
View File
@@ -1,25 +1,25 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
; Copyright (c) 2001-2008 Stephen Williams ([email protected])
; Copyright (c) 2001-2014 Stephen Williams ([email protected])
;
; 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 free software; you can redistribute it and/or modify
; it 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
; 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
; This example is similar to the code that the following Verilog program
; would make:
; would generate:
;
; module main;
; initial #45 $display("Hello, Clock: ", $time);
@@ -28,11 +28,11 @@
; This tests that the special $time symbol references the vpiHandle for
; the system time.
main .scope module, "main";
code
%delay 45, 0;
%vpi_call 0 0 "$display", "Hello, Clock: ", $time;
main .scope module, "main" "main" 0 0;
code %delay 45, 0;
%vpi_call 0 0 "$display", "Hello, Clock: ", $time {0 0 0};
%end;
.thread code;
:file_names 2;
+25 -2
View File
@@ -1,8 +1,31 @@
:ivl_version "0.10.0" "vec4-stack";
:vpi_module "system";
main .scope module, "main";
; This program is free software; you can redistribute it and/or modify
; it 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.,
; 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
T0 %vpi_call 0 0 "$display", "Display the number: %b", 5'b0zx1;
; This example is similar to the code that the following Verilog program
; would generate:
;
; module main;
; initial $display("Display the number: %b", 5'b0zx1);
; endmodule
main .scope module, "main" "main" 0 0;
T0 %vpi_call 0 0 "$display", "Display the number: %b", 5'b0zx1 {0 0 0};
%end;
.thread T0;
:file_names 2;
+63 -25
View File
@@ -50,22 +50,6 @@ extern const char hex_digits[256];
extern const char oct_digits[64];
#ifdef CHECK_WITH_VALGRIND
static map<vpiHandle, bool> handle_map;
void thread_vthr_delete(vpiHandle item)
{
handle_map[item] = true;
}
static void thread_vthr_delete_real(vpiHandle item)
{
struct __vpiVThrVec*obj = dynamic_cast<__vpiVThrVec*>(item);
delete obj;
}
#endif
struct __vpiVThrWord : public __vpiHandle {
__vpiVThrWord();
int get_type_code(void) const;
@@ -200,6 +184,8 @@ vpiHandle vpip_make_vthr_word(unsigned base, const char*type)
}
#ifdef CHECK_WITH_VALGRIND
static map<vpiHandle, bool> handle_map;
void thread_word_delete(vpiHandle item)
{
handle_map[item] = false;
@@ -210,15 +196,6 @@ static void thread_word_delete_real(vpiHandle item)
struct __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(item);
delete obj;
}
void vpi_handle_delete()
{
map<vpiHandle, bool>::iterator iter;
for (iter = handle_map.begin(); iter != handle_map.end(); ++ iter ) {
if (iter->second) thread_vthr_delete_real(iter->first);
else thread_word_delete_real(iter->first);
}
}
#endif
class __vpiVThrStrStack : public __vpiHandle {
@@ -294,6 +271,7 @@ class __vpiVThrVec4Stack : public __vpiHandle {
void vpi_get_value_decstr_(p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_int_ (p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_real_ (p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_strength_(p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_hexstr_(p_vpi_value vp, const vvp_vector4_t&val);
void vpi_get_value_vector_(p_vpi_value vp, const vvp_vector4_t&val);
private:
@@ -373,6 +351,9 @@ void __vpiVThrVec4Stack::vpi_get_value(p_vpi_value vp)
case vpiStringVal:
vpi_get_value_string_(vp, val);
break;
case vpiStrengthVal:
vpi_get_value_strength_(vp, val);
break;
case vpiObjTypeVal:
vp->format = vpiVectorVal;
case vpiVectorVal:
@@ -533,6 +514,40 @@ void __vpiVThrVec4Stack::vpi_get_value_vector_(p_vpi_value vp, const vvp_vector4
}
}
void __vpiVThrVec4Stack::vpi_get_value_strength_(p_vpi_value vp, const vvp_vector4_t&val)
{
s_vpi_strengthval*op = (s_vpi_strengthval*)
need_result_buf(val.size() * sizeof(s_vpi_strengthval), RBUF_VAL);
for (unsigned idx = 0 ; idx < val.size() ; idx += 1) {
switch (val.value(idx)) {
case BIT4_0:
op[idx].logic = vpi0;
op[idx].s0 = vpiStrongDrive;
op[idx].s1 = 0;
break;
case BIT4_1:
op[idx].logic = vpi1;
op[idx].s0 = 0;
op[idx].s1 = vpiStrongDrive;
break;
case BIT4_X:
op[idx].logic = vpiX;
op[idx].s0 = vpiStrongDrive;
op[idx].s1 = vpiStrongDrive;
break;
case BIT4_Z:
op[idx].logic = vpiZ;
op[idx].s0 = vpiHiZ;
op[idx].s1 = vpiHiZ;
break;
}
}
vp->format = vpiStrengthVal;
vp->value.strength = op;
}
vpiHandle __vpiVThrVec4Stack::vpi_put_value(p_vpi_value vp, int /*flags*/)
{
assert(vpip_current_vthread);
@@ -547,6 +562,29 @@ vpiHandle __vpiVThrVec4Stack::vpi_put_value(p_vpi_value vp, int /*flags*/)
}
}
#ifdef CHECK_WITH_VALGRIND
void thread_vthr_delete(vpiHandle item)
{
handle_map[item] = true;
}
static void thread_vthr_delete_real(vpiHandle item)
{
class __vpiVThrVec4Stack*obj = dynamic_cast<__vpiVThrVec4Stack*>(item);
delete obj;
}
void vpi_handle_delete()
{
map<vpiHandle, bool>::iterator iter;
for (iter = handle_map.begin(); iter != handle_map.end(); ++ iter ) {
if (iter->second) thread_vthr_delete_real(iter->first);
else thread_word_delete_real(iter->first);
}
}
#endif
vpiHandle vpip_make_vthr_str_stack(unsigned depth)
{
class __vpiVThrStrStack*obj = new __vpiVThrStrStack(depth);
+13 -4
View File
@@ -248,6 +248,7 @@ struct vthread_s {
unsigned i_am_detached :1;
unsigned i_am_waiting :1;
unsigned i_have_ended :1;
unsigned i_was_disabled :1;
unsigned waiting_for_event :1;
unsigned is_scheduled :1;
unsigned delay_delete :1;
@@ -271,6 +272,12 @@ struct vthread_s {
inline void cleanup()
{
if (i_was_disabled) {
stack_vec4_.clear();
stack_real_.clear();
stack_str_.clear();
pop_object(stack_obj_size_);
}
assert(stack_vec4_.empty());
assert(stack_real_.empty());
assert(stack_str_.empty());
@@ -499,6 +506,7 @@ vthread_t vthread_new(vvp_code_t pc, struct __vpiScope*scope)
thr->i_am_waiting = 0;
thr->is_scheduled = 0;
thr->i_have_ended = 0;
thr->i_was_disabled = 0;
thr->delay_delete = 0;
thr->waiting_for_event = 0;
thr->event = 0;
@@ -2173,6 +2181,7 @@ static bool do_disable(vthread_t thr, vthread_t match)
/* Turn the thread off by setting is program counter to
zero and setting an OFF bit. */
thr->pc = codespace_null();
thr->i_was_disabled = 1;
thr->i_have_ended = 1;
/* Turn off all the children of the thread. Simulate a %join
@@ -3073,13 +3082,13 @@ static uint64_t vec4_to_index(vthread_t thr, bool signed_flag)
// Set the high bits that are not necessarily filled in by the
// subarray function.
if (val_size < 8*sizeof(v)) {
if (signed_flag && (v & (1UL<<(val_size-1)))) {
if (signed_flag && (v & (static_cast<uint64_t>(1)<<(val_size-1)))) {
// Propagate the sign bit...
v |= -1UL << val_size;
v |= (~static_cast<uint64_t>(0)) << val_size;
} else {
// Fill with zeros.
v &= ~(-1UL << val_size);
v &= ~((~static_cast<uint64_t>(0)) << val_size);
}
}
@@ -5785,7 +5794,6 @@ bool of_EXEC_UFUNC(vthread_t thr, vvp_code_t cp)
child->wt_context = child_context;
child->rd_context = child_context;
child->parent = thr;
child->is_scheduled = 1;
vthread_run(child);
running_thread = thr;
@@ -5793,6 +5801,7 @@ bool of_EXEC_UFUNC(vthread_t thr, vvp_code_t cp)
if (child->i_have_ended)
return true;
child->parent = thr;
thr->children.insert(child);
thr->i_am_joining = 1;
return false;