mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-25 07:16:52 +02:00
Compare commits
28
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0fecdcbeda | ||
|
|
23ad62f317 | ||
|
|
ac20008606 | ||
|
|
96d181efed | ||
|
|
18bfe7d497 | ||
|
|
86562e60ba | ||
|
|
b400532169 | ||
|
|
6fd10dedb6 | ||
|
|
c8255952a3 | ||
|
|
71c4ea36e8 | ||
|
|
5df179cd5f | ||
|
|
ce5c4ca8ba | ||
|
|
6aa8e49b09 | ||
|
|
f29f4ff4e3 | ||
|
|
3ccc59eaa3 | ||
|
|
0282b8450c | ||
|
|
43841af2f3 | ||
|
|
b2d8d41e3f | ||
|
|
0e38843ae9 | ||
|
|
96472e5537 | ||
|
|
48b0fed29e | ||
|
|
1efa220773 | ||
|
|
2d6622e543 | ||
|
|
edf112b900 | ||
|
|
f0a0ab100f | ||
|
|
c28188618b | ||
|
|
0d7daf5862 | ||
|
|
60ab1daa1f |
@@ -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
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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); }
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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*>*);
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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.
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user