mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-24 06:46:52 +02:00
Compare commits
17
Commits
v11-branch
...
array-copy
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c2fb6a601 | ||
|
|
7277f4e807 | ||
|
|
919fd22a79 | ||
|
|
156644d91e | ||
|
|
292d174cad | ||
|
|
b14a623eef | ||
|
|
1b3f0dd689 | ||
|
|
0fada92389 | ||
|
|
ad862020bb | ||
|
|
d209e7533a | ||
|
|
d6e01d0c55 | ||
|
|
359b2b65c2 | ||
|
|
6566072741 | ||
|
|
8f8737198c | ||
|
|
4e79c1c861 | ||
|
|
6880b39770 | ||
|
|
c4883da334 |
+3
-2
@@ -43,7 +43,7 @@ void PFunction::set_statement(Statement*s)
|
||||
|
||||
void PFunction::push_statement_front(Statement*stmt)
|
||||
{
|
||||
// This can only happen after the statement is initially set.
|
||||
// This should not be possible.
|
||||
ivl_assert(*this, statement_);
|
||||
|
||||
// Get the PBlock of the statement. If it is not a PBlock,
|
||||
@@ -75,7 +75,8 @@ PChainConstructor* PFunction::extract_chain_constructor()
|
||||
PChainConstructor*res = 0;
|
||||
|
||||
if ((res = dynamic_cast<PChainConstructor*> (statement_))) {
|
||||
statement_ = 0;
|
||||
statement_ = new PBlock(PBlock::BL_SEQ);
|
||||
statement_->set_line(*this);
|
||||
|
||||
} else if (PBlock*blk = dynamic_cast<PBlock*>(statement_)) {
|
||||
res = blk->extract_chain_constructor();
|
||||
|
||||
+20
-16
@@ -1958,6 +1958,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
unsigned long use_width = struct_type->packed_width();
|
||||
|
||||
pform_name_t completed_path;
|
||||
ivl_type_t member_type = 0;
|
||||
do {
|
||||
const name_component_t member_comp = member_path.front();
|
||||
const perm_string&member_name = member_comp.name;
|
||||
@@ -1985,28 +1986,29 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
member_type = member->net_type;
|
||||
if (debug_elaborate) {
|
||||
cerr << li->get_fileline() << ": check_for_struct_members: "
|
||||
<< "Member type: " << *(member->net_type)
|
||||
<< " (" << typeid(*(member->net_type)).name() << ")"
|
||||
<< "Member type: " << *member_type
|
||||
<< " (" << typeid(*member_type).name() << ")"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
off += tmp_off;
|
||||
ivl_assert(*li, use_width >= (unsigned long)member->net_type->packed_width());
|
||||
use_width = member->net_type->packed_width();
|
||||
ivl_assert(*li, use_width >= (unsigned long)member_type->packed_width());
|
||||
use_width = member_type->packed_width();
|
||||
|
||||
// At this point, off and use_width are the part select
|
||||
// expressed by the member_comp, which is a member of the
|
||||
// struct. We can further refine the part select with any
|
||||
// indices that might be present.
|
||||
|
||||
if (const netstruct_t*tmp_struct = dynamic_cast<const netstruct_t*>(member->net_type)) {
|
||||
if (const netstruct_t*tmp_struct = dynamic_cast<const netstruct_t*>(member_type)) {
|
||||
// If the member is itself a struct, then get
|
||||
// ready to go on to the next iteration.
|
||||
struct_type = tmp_struct;
|
||||
|
||||
} else if (const netenum_t*tmp_enum = dynamic_cast<const netenum_t*> (member->net_type)) {
|
||||
} else if (const netenum_t*tmp_enum = dynamic_cast<const netenum_t*> (member_type)) {
|
||||
|
||||
// If the element is an enum, then we don't have
|
||||
// anything special to do.
|
||||
@@ -2017,7 +2019,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
}
|
||||
struct_type = 0;
|
||||
|
||||
} else if (const netvector_t*mem_vec = dynamic_cast<const netvector_t*>(member->net_type)) {
|
||||
} else if (const netvector_t*mem_vec = dynamic_cast<const netvector_t*>(member_type)) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << li->get_fileline() << ": check_for_struct_members: "
|
||||
@@ -2104,7 +2106,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
// there is no next struct type.
|
||||
struct_type = 0;
|
||||
|
||||
} else if (const netparray_t*array = dynamic_cast<const netparray_t*>(member->net_type)) {
|
||||
} else if (const netparray_t*array = dynamic_cast<const netparray_t*>(member_type)) {
|
||||
|
||||
// If the member is a parray, then the elements
|
||||
// are themselves packed object, including
|
||||
@@ -2178,7 +2180,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
} else {
|
||||
// Unknown type?
|
||||
cerr << li->get_fileline() << ": internal error: "
|
||||
<< "Unexpected member type? " << *(member->net_type)
|
||||
<< "Unexpected member type? " << *member_type
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
struct_type = 0;
|
||||
@@ -2224,7 +2226,7 @@ static NetExpr* check_for_struct_members(const LineInfo*li,
|
||||
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
NetExpr *base = packed_base? packed_base : make_const_val(off);
|
||||
NetESelect*sel = new NetESelect(sig, base, use_width);
|
||||
NetESelect*sel = new NetESelect(sig, base, use_width, member_type);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << li->get_fileline() << ": check_for_struct_member: "
|
||||
@@ -2599,7 +2601,7 @@ NetExpr* PECallFunction::elaborate_expr_method_(Design*des, NetScope*scope,
|
||||
/* Add the implicit this reference when requested. */
|
||||
if (add_this_flag) {
|
||||
assert(use_path.empty());
|
||||
use_path.push_front(name_component_t(perm_string::literal("@")));
|
||||
use_path.push_front(name_component_t(perm_string::literal(THIS_TOKEN)));
|
||||
}
|
||||
|
||||
// If there is no object to the left of the method name, then
|
||||
@@ -3904,7 +3906,7 @@ NetExpr* PEIdent::elaborate_expr_class_member_(Design*des, NetScope*scope,
|
||||
NetScope*scope_method = find_method_containing_scope(*this, scope);
|
||||
ivl_assert(*this, scope_method);
|
||||
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
if (this_net == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find 'this' port of " << scope_path(scope_method)
|
||||
@@ -5395,7 +5397,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
cerr << get_fileline() << ": debug: "
|
||||
<< "Bit select of a dynamic array becomes NetESelect." << endl;
|
||||
}
|
||||
NetESelect*res = new NetESelect(net, mux, darray->element_width());
|
||||
NetESelect*res = new NetESelect(net, mux, darray->element_width(), darray->element_type());
|
||||
res->set_line(*net);
|
||||
return res;
|
||||
}
|
||||
@@ -5597,13 +5599,15 @@ NetExpr* PEIdent::elaborate_expr_net_bit_last_(Design*, NetScope*,
|
||||
}
|
||||
|
||||
unsigned use_width = 1;
|
||||
ivl_type_t use_type = 0;
|
||||
if (const netdarray_t*darray = net->sig()->darray_type()) {
|
||||
use_width = darray->element_width();
|
||||
use_type = darray->element_type();
|
||||
}
|
||||
|
||||
NetELast*mux = new NetELast(net->sig());
|
||||
mux->set_line(*this);
|
||||
NetESelect*ss = new NetESelect(net, mux, use_width);
|
||||
NetESelect*ss = new NetESelect(net, mux, use_width, use_type);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
@@ -5762,7 +5766,7 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
||||
|
||||
// The return value of the initializer is the "this"
|
||||
// variable, instead of the "new&" scope name.
|
||||
NetNet*res1 = new1_scope->find_signal(perm_string::literal("@"));
|
||||
NetNet*res1 = new1_scope->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
ivl_assert(*this, res1);
|
||||
|
||||
NetESignal*eres = new NetESignal(res1);
|
||||
@@ -5849,7 +5853,7 @@ NetExpr* PENewClass::elaborate_expr_constructor_(Design*des, NetScope*scope,
|
||||
|
||||
// The return value for the constructor is actually the "this"
|
||||
// variable, instead of the "new" scope name.
|
||||
NetNet*res = new_scope->find_signal(perm_string::literal("@"));
|
||||
NetNet*res = new_scope->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
ivl_assert(*this, res);
|
||||
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
|
||||
+1
-1
@@ -378,7 +378,7 @@ NetAssign_* PEIdent::elaborate_lval_method_class_member_(Design*des,
|
||||
NetScope*scope_method = find_method_containing_scope(*this, scope);
|
||||
ivl_assert(*this, scope_method);
|
||||
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal("@"));
|
||||
NetNet*this_net = scope_method->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
if (this_net == 0) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "Unable to find 'this' port of " << scope_path(scope_method)
|
||||
|
||||
+5
-1
@@ -966,7 +966,11 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
// block. Code within this scope thus has access to the
|
||||
// genvar as a constant.
|
||||
{
|
||||
verinum genvar_verinum(genvar);
|
||||
verinum genvar_verinum;
|
||||
if (gn_strict_expr_width_flag)
|
||||
genvar_verinum = verinum(genvar, integer_width);
|
||||
else
|
||||
genvar_verinum = verinum(genvar);
|
||||
genvar_verinum.has_sign(true);
|
||||
NetEConstParam*gp = new NetEConstParam(scope,
|
||||
loop_index,
|
||||
|
||||
+4
-4
@@ -578,10 +578,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
// source code for the definition may be:
|
||||
// function new(...);
|
||||
// endfunction
|
||||
// In this case, the "@" port is the synthetic "this"
|
||||
// argument and we also use it as a return value at the
|
||||
// same time.
|
||||
ret_sig = scope->find_signal(perm_string::literal("@"));
|
||||
// In this case, the "@" port (THIS_TOKEN) is the synthetic
|
||||
// "this" argument and we also use it as a return value at
|
||||
// the same time.
|
||||
ret_sig = scope->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
ivl_assert(*this, ret_sig);
|
||||
|
||||
if (debug_elaborate)
|
||||
|
||||
+33
-2
@@ -110,6 +110,18 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
return;
|
||||
}
|
||||
|
||||
if (lval->enumeration()) {
|
||||
if (! rval_expr->enumeration()) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"This assignment requires an explicit cast." << endl;
|
||||
des->errors += 1;
|
||||
} else if (! lval->enumeration()->matches(rval_expr->enumeration())) {
|
||||
cerr << get_fileline() << ": error: "
|
||||
"Enumeration type mismatch in assignment." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
}
|
||||
|
||||
NetNet*rval = rval_expr->synthesize(des, scope, rval_expr);
|
||||
|
||||
if (rval == 0) {
|
||||
@@ -2990,6 +3002,25 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
for (unsigned idx = 0 ; idx < list_.size() ; idx += 1) {
|
||||
assert(list_[idx]);
|
||||
|
||||
// Detect the error that a super.new() statement is in the
|
||||
// midst of a block. Report the error. Continue on with the
|
||||
// elaboration so that other errors might be found.
|
||||
if (PChainConstructor*supernew = dynamic_cast<PChainConstructor*> (list_[idx])) {
|
||||
if (debug_elaborate) {
|
||||
cerr << get_fileline() << ": PBlock::elaborate: "
|
||||
<< "Found super.new statement, idx=" << idx << ", "
|
||||
<< " at " << supernew->get_fileline() << "."
|
||||
<< endl;
|
||||
}
|
||||
if (idx > 0) {
|
||||
des->errors += 1;
|
||||
cerr << supernew->get_fileline() << ": error: "
|
||||
<< "super.new(...) must be the first statement in a block."
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
|
||||
NetProc*tmp = list_[idx]->elaborate(des, nscope);
|
||||
// If the statement fails to elaborate, then simply
|
||||
// ignore it. Presumably, the elaborate for the
|
||||
@@ -3254,7 +3285,7 @@ NetProc* PChainConstructor::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
// Need the "this" variable for the current constructor. We're
|
||||
// going to pass this to the chained constructor.
|
||||
NetNet*var_this = scope->find_signal(perm_string::literal("@"));
|
||||
NetNet*var_this = scope->find_signal(perm_string::literal(THIS_TOKEN));
|
||||
|
||||
// If super.new is an implicit constructor, then there are no
|
||||
// arguments (other than "this" to worry about, so make a
|
||||
@@ -3716,7 +3747,7 @@ NetProc* PCallTask::elaborate_method_(Design*des, NetScope*scope,
|
||||
/* Add the implicit this reference when requested. */
|
||||
if (add_this_flag) {
|
||||
assert(use_path.empty());
|
||||
use_path.push_front(name_component_t(perm_string::literal("@")));
|
||||
use_path.push_front(name_component_t(perm_string::literal(THIS_TOKEN)));
|
||||
}
|
||||
|
||||
// There is no signal to search for so this cannot be a method.
|
||||
|
||||
+35
-5
@@ -154,9 +154,9 @@ static void ifdef_leave(void)
|
||||
result = (rc == 0) ? YY_NULL : rc; \
|
||||
} else { \
|
||||
/* We are expanding a macro. Handle the SV `` delimiter. \
|
||||
If the delimiter terminates a compiler directive, leave \
|
||||
If the delimiter terminates a defined macro usage, leave \
|
||||
it in place, otherwise remove it now. */ \
|
||||
if (yytext[0] != '`') { \
|
||||
if (!(yytext[0] == '`' && is_defined(yytext+1))) { \
|
||||
while ((istack->str[0] == '`') && \
|
||||
(istack->str[1] == '`')) { \
|
||||
istack->str += 2; \
|
||||
@@ -186,9 +186,11 @@ static int ma_parenthesis_level = 0;
|
||||
|
||||
%x PPINCLUDE
|
||||
%x DEF_NAME
|
||||
%x DEF_ESC
|
||||
%x DEF_ARG
|
||||
%x DEF_SEP
|
||||
%x DEF_TXT
|
||||
%x MN_ESC
|
||||
%x MA_START
|
||||
%x MA_ADD
|
||||
%x CCOMMENT
|
||||
@@ -338,6 +340,11 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*"("{W}? { BEGIN(DEF_ARG); def_start(); }
|
||||
<DEF_NAME>[a-zA-Z_][a-zA-Z0-9_$]*{W}? { BEGIN(DEF_TXT); def_start(); }
|
||||
|
||||
<DEF_NAME>\\ { BEGIN(DEF_ESC); }
|
||||
|
||||
<DEF_ESC>[^ \t\b\f\n\r]+{W}"("{W}? { BEGIN(DEF_ARG); def_start(); }
|
||||
<DEF_ESC>[^ \t\b\f\n\r]+{W} { BEGIN(DEF_TXT); def_start(); }
|
||||
|
||||
/* define arg: <name> = <text> */
|
||||
<DEF_ARG>[a-zA-Z_][a-zA-Z0-9_$]*{W}*"="[^,\)]*{W}? { BEGIN(DEF_SEP); def_add_arg(); }
|
||||
/* define arg: <name> */
|
||||
@@ -352,7 +359,7 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
|
||||
<DEF_ARG,DEF_SEP>(\n|"\r\n"|"\n\r"|\r){W}? { istack->lineno += 1; fputc('\n', yyout); }
|
||||
|
||||
<DEF_NAME,DEF_ARG,DEF_SEP>. {
|
||||
<DEF_NAME,DEF_ESC,DEF_ARG,DEF_SEP>. {
|
||||
emit_pathline(istack);
|
||||
fprintf(stderr, "error: malformed `define directive.\n");
|
||||
error_count += 1;
|
||||
@@ -535,6 +542,24 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif)
|
||||
do_expand(0);
|
||||
}
|
||||
|
||||
`\\ { yy_push_state(MN_ESC); }
|
||||
|
||||
<MN_ESC>[^ \t\b\f\n\r]+ {
|
||||
yy_pop_state();
|
||||
if (macro_needs_args(yytext))
|
||||
yy_push_state(MA_START);
|
||||
else
|
||||
do_expand(0);
|
||||
}
|
||||
|
||||
<MN_ESC>. {
|
||||
yy_pop_state();
|
||||
unput(yytext[0]);
|
||||
emit_pathline(istack);
|
||||
fprintf(stderr, "error: malformed macro name.\n");
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
/* Stringified version of macro expansion. This is an Icarus extension.
|
||||
When expanding macro text, the SV usage of `` takes precedence. */
|
||||
``[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
@@ -825,8 +850,13 @@ static void def_add_arg(void)
|
||||
|
||||
/* 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--;
|
||||
as name(, so chop off the ( here. If we have an escaped name,
|
||||
we also need to strip off the white space that terminates the
|
||||
name. */
|
||||
if (yytext[length - 1] == '(') {
|
||||
length--;
|
||||
while (isspace((int)yytext[length - 1])) length--;
|
||||
}
|
||||
|
||||
yytext[length] = 0;
|
||||
|
||||
|
||||
+17
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2002-2019 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2002-2020 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
|
||||
@@ -403,7 +403,14 @@ ivl_variable_type_t NetEProperty::expr_type() const
|
||||
|
||||
NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid,
|
||||
ivl_select_type_t sel_type)
|
||||
: expr_(exp), base_(base), sel_type_(sel_type)
|
||||
: expr_(exp), base_(base), use_type_(0), sel_type_(sel_type)
|
||||
{
|
||||
expr_width(wid);
|
||||
}
|
||||
|
||||
NetESelect::NetESelect(NetExpr*exp, NetExpr*base, unsigned wid,
|
||||
ivl_type_t use_type)
|
||||
: expr_(exp), base_(base), use_type_(use_type), sel_type_(IVL_SEL_OTHER)
|
||||
{
|
||||
expr_width(wid);
|
||||
}
|
||||
@@ -431,6 +438,9 @@ ivl_select_type_t NetESelect::select_type() const
|
||||
|
||||
ivl_variable_type_t NetESelect::expr_type() const
|
||||
{
|
||||
if (use_type_)
|
||||
return use_type_->base_type();
|
||||
|
||||
ivl_variable_type_t type = expr_->expr_type();
|
||||
|
||||
// Special case: If the sub-expression is an IVL_VT_STRING,
|
||||
@@ -439,20 +449,12 @@ ivl_variable_type_t NetESelect::expr_type() const
|
||||
if (type == IVL_VT_STRING && expr_width()==8)
|
||||
return IVL_VT_BOOL;
|
||||
|
||||
if (type != IVL_VT_DARRAY)
|
||||
return type;
|
||||
return type;
|
||||
}
|
||||
|
||||
ivl_assert(*this, type == IVL_VT_DARRAY);
|
||||
|
||||
// Special case: If the expression is a DARRAY, then the
|
||||
// sub-expression must be a NetESignal and the type of the
|
||||
// NetESelect expression is the element type of the arrayed signal.
|
||||
NetESignal*sig = dynamic_cast<NetESignal*>(expr_);
|
||||
ivl_assert(*this, sig);
|
||||
const netarray_t*array_type = dynamic_cast<const netarray_t*> (sig->sig()->net_type());
|
||||
ivl_assert(*this, array_type);
|
||||
|
||||
return array_type->element_type()->base_type();
|
||||
const netenum_t* NetESelect::enumeration() const
|
||||
{
|
||||
return dynamic_cast<const netenum_t*> (use_type_);
|
||||
}
|
||||
|
||||
bool NetESelect::has_width() const
|
||||
|
||||
@@ -4401,21 +4401,29 @@ class NetEConcat : public NetExpr {
|
||||
* If the base expression is null, then this expression node can be
|
||||
* used to express width expansion, signed or unsigned depending on
|
||||
* the has_sign() flag.
|
||||
*
|
||||
* An alternative form of this expression node is used for dynamic
|
||||
* array word selects and for packed struct member selects. In this
|
||||
* case use_type indicates the type of the selected element/member.
|
||||
*/
|
||||
class NetESelect : public NetExpr {
|
||||
|
||||
public:
|
||||
NetESelect(NetExpr*exp, NetExpr*base, unsigned wid,
|
||||
ivl_select_type_t sel_type = IVL_SEL_OTHER);
|
||||
NetESelect(NetExpr*exp, NetExpr*base, unsigned wid,
|
||||
ivl_type_t use_type);
|
||||
~NetESelect();
|
||||
|
||||
const NetExpr*sub_expr() const;
|
||||
const NetExpr*select() const;
|
||||
ivl_select_type_t select_type() const;
|
||||
|
||||
// The type of a NetESelect is the base type of the
|
||||
// sub-expression.
|
||||
// The type of a bit/part select is the base type of the
|
||||
// sub-expression. The type of an array/member select is
|
||||
// the base type of the element/member.
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
virtual const netenum_t* enumeration() const;
|
||||
|
||||
virtual NexusSet* nex_input(bool rem_out = true, bool always_sens = false,
|
||||
bool nested_func = false) const;
|
||||
@@ -4431,6 +4439,7 @@ class NetESelect : public NetExpr {
|
||||
private:
|
||||
NetExpr*expr_;
|
||||
NetExpr*base_;
|
||||
ivl_type_t use_type_;
|
||||
ivl_select_type_t sel_type_;
|
||||
};
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ static LexicalScope::lifetime_t var_lifetime;
|
||||
|
||||
static pform_name_t* pform_create_this(void)
|
||||
{
|
||||
name_component_t name (perm_string::literal("@"));
|
||||
name_component_t name (perm_string::literal(THIS_TOKEN));
|
||||
pform_name_t*res = new pform_name_t;
|
||||
res->push_back(name);
|
||||
return res;
|
||||
@@ -76,7 +76,7 @@ static pform_name_t* pform_create_this(void)
|
||||
|
||||
static pform_name_t* pform_create_super(void)
|
||||
{
|
||||
name_component_t name (perm_string::literal("#"));
|
||||
name_component_t name (perm_string::literal(SUPER_TOKEN));
|
||||
pform_name_t*res = new pform_name_t;
|
||||
res->push_back(name);
|
||||
return res;
|
||||
@@ -1364,6 +1364,8 @@ description /* IEEE1800-2005: A.1.2 */
|
||||
delete[] $3;
|
||||
delete[] $5;
|
||||
}
|
||||
| ';'
|
||||
{ }
|
||||
;
|
||||
|
||||
description_list
|
||||
@@ -2321,7 +2323,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope(@1, $3, $2);
|
||||
}
|
||||
tf_port_list ')' ';'
|
||||
tf_port_list_opt ')' ';'
|
||||
block_item_decls_opt
|
||||
statement_or_null_list_opt
|
||||
K_endtask
|
||||
@@ -2329,6 +2331,10 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||
current_task_set_statement(@3, $10);
|
||||
pform_set_this_class(@3, current_task);
|
||||
pform_pop_scope();
|
||||
if (generation_flag < GN_VER2005 && $6 == 0) {
|
||||
cerr << @3 << ": warning: task definition for \"" << $3
|
||||
<< "\" has an empty port declaration list!" << endl;
|
||||
}
|
||||
current_task = 0;
|
||||
if ($10) delete $10;
|
||||
}
|
||||
@@ -2351,46 +2357,6 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
||||
delete[]$3;
|
||||
}
|
||||
|
||||
| K_task lifetime_opt IDENTIFIER '(' ')' ';'
|
||||
{ assert(current_task == 0);
|
||||
current_task = pform_push_task_scope(@1, $3, $2);
|
||||
}
|
||||
block_item_decls_opt
|
||||
statement_or_null_list
|
||||
K_endtask
|
||||
{ current_task->set_ports(0);
|
||||
current_task_set_statement(@3, $9);
|
||||
pform_set_this_class(@3, current_task);
|
||||
if (! current_task->method_of()) {
|
||||
cerr << @3 << ": warning: task definition for \"" << $3
|
||||
<< "\" has an empty port declaration list!" << endl;
|
||||
}
|
||||
pform_pop_scope();
|
||||
current_task = 0;
|
||||
if ($9->size() > 1 && !gn_system_verilog()) {
|
||||
yyerror(@9, "error: Task body with multiple statements requires SystemVerilog.");
|
||||
}
|
||||
delete $9;
|
||||
}
|
||||
endlabel_opt
|
||||
{ // Last step: check any closing name. This is done late so
|
||||
// that the parser can look ahead to detect the present
|
||||
// endlabel_opt but still have the pform_endmodule() called
|
||||
// early enough that the lexor can know we are outside the
|
||||
// module.
|
||||
if ($12) {
|
||||
if (strcmp($3,$12) != 0) {
|
||||
yyerror(@12, "error: End label doesn't match task name");
|
||||
}
|
||||
if (! gn_system_verilog()) {
|
||||
yyerror(@12, "error: Task end labels require "
|
||||
"SystemVerilog.");
|
||||
}
|
||||
delete[]$12;
|
||||
}
|
||||
delete[]$3;
|
||||
}
|
||||
|
||||
| K_task lifetime_opt IDENTIFIER error K_endtask
|
||||
{
|
||||
if (current_task) {
|
||||
@@ -5315,14 +5281,14 @@ module_item
|
||||
{ pform_endgenerate(false); }
|
||||
|
||||
| generate_if
|
||||
generate_block_opt
|
||||
generate_block
|
||||
K_else
|
||||
{ pform_start_generate_else(@1); }
|
||||
generate_block
|
||||
{ pform_endgenerate(true); }
|
||||
|
||||
| generate_if
|
||||
generate_block_opt %prec less_than_K_else
|
||||
generate_block %prec less_than_K_else
|
||||
{ pform_endgenerate(true); }
|
||||
|
||||
| K_case '(' expression ')'
|
||||
@@ -5360,50 +5326,51 @@ module_item
|
||||
module items. These rules try to catch them at a point where a
|
||||
reasonable error message can be produced. */
|
||||
|
||||
| error ';'
|
||||
{ yyerror(@2, "error: invalid module item.");
|
||||
yyerrok;
|
||||
}
|
||||
| error ';'
|
||||
{ yyerror(@2, "error: invalid module item.");
|
||||
yyerrok;
|
||||
}
|
||||
|
||||
| K_assign error '=' expression ';'
|
||||
{ yyerror(@1, "error: syntax error in left side "
|
||||
"of continuous assignment.");
|
||||
yyerrok;
|
||||
}
|
||||
| K_assign error '=' expression ';'
|
||||
{ yyerror(@1, "error: syntax error in left side of "
|
||||
"continuous assignment.");
|
||||
yyerrok;
|
||||
}
|
||||
|
||||
| K_assign error ';'
|
||||
{ yyerror(@1, "error: syntax error in "
|
||||
"continuous assignment");
|
||||
yyerrok;
|
||||
}
|
||||
| K_assign error ';'
|
||||
{ yyerror(@1, "error: syntax error in continuous assignment");
|
||||
yyerrok;
|
||||
}
|
||||
|
||||
| K_function error K_endfunction endlabel_opt
|
||||
{ yyerror(@1, "error: I give up on this "
|
||||
"function definition.");
|
||||
if ($4) {
|
||||
if (!gn_system_verilog()) {
|
||||
yyerror(@4, "error: Function end names require "
|
||||
"SystemVerilog.");
|
||||
}
|
||||
delete[]$4;
|
||||
}
|
||||
yyerrok;
|
||||
}
|
||||
| K_function error K_endfunction endlabel_opt
|
||||
{ yyerror(@1, "error: I give up on this function definition.");
|
||||
if ($4) {
|
||||
if (!gn_system_verilog()) {
|
||||
yyerror(@4, "error: Function end names require "
|
||||
"SystemVerilog.");
|
||||
}
|
||||
delete[]$4;
|
||||
}
|
||||
yyerrok;
|
||||
}
|
||||
|
||||
/* These rules are for the Icarus Verilog specific $attribute
|
||||
extensions. Then catch the parameters of the $attribute keyword. */
|
||||
|
||||
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')' ';'
|
||||
{ perm_string tmp3 = lex_strings.make($3);
|
||||
perm_string tmp5 = lex_strings.make($5);
|
||||
pform_set_attrib(tmp3, tmp5, $7);
|
||||
delete[] $3;
|
||||
delete[] $5;
|
||||
}
|
||||
| KK_attribute '(' error ')' ';'
|
||||
{ yyerror(@1, "error: Malformed $attribute parameter list."); }
|
||||
| KK_attribute '(' IDENTIFIER ',' STRING ',' STRING ')' ';'
|
||||
{ perm_string tmp3 = lex_strings.make($3);
|
||||
perm_string tmp5 = lex_strings.make($5);
|
||||
pform_set_attrib(tmp3, tmp5, $7);
|
||||
delete[] $3;
|
||||
delete[] $5;
|
||||
}
|
||||
| KK_attribute '(' error ')' ';'
|
||||
{ yyerror(@1, "error: Malformed $attribute parameter list."); }
|
||||
|
||||
;
|
||||
| ';'
|
||||
{ }
|
||||
|
||||
;
|
||||
|
||||
module_item_list
|
||||
: module_item_list module_item
|
||||
@@ -5423,9 +5390,9 @@ generate_case_items
|
||||
;
|
||||
|
||||
generate_case_item
|
||||
: expression_list_proper ':' { pform_generate_case_item(@1, $1); } generate_block_opt
|
||||
: expression_list_proper ':' { pform_generate_case_item(@1, $1); } generate_block
|
||||
{ pform_endgenerate(false); }
|
||||
| K_default ':' { pform_generate_case_item(@1, 0); } generate_block_opt
|
||||
| K_default ':' { pform_generate_case_item(@1, 0); } generate_block
|
||||
{ pform_endgenerate(false); }
|
||||
;
|
||||
|
||||
@@ -5487,9 +5454,6 @@ generate_block
|
||||
}
|
||||
;
|
||||
|
||||
generate_block_opt : generate_block | ';' ;
|
||||
|
||||
|
||||
/* A net declaration assignment allows the programmer to combine the
|
||||
net declaration and the continuous assignment into a single
|
||||
statement.
|
||||
@@ -6933,6 +6897,9 @@ statement_item /* This is roughly statement_item in the LRM */
|
||||
| implicit_class_handle '.' K_new '(' expression_list_with_nuls ')' ';'
|
||||
{ PChainConstructor*tmp = new PChainConstructor(*$5);
|
||||
FILE_NAME(tmp, @3);
|
||||
if (peek_head_name(*$1) == THIS_TOKEN) {
|
||||
yyerror(@1, "error: this.new is invalid syntax. Did you mean super.new?");
|
||||
}
|
||||
delete $1;
|
||||
$$ = tmp;
|
||||
}
|
||||
|
||||
@@ -297,7 +297,7 @@ void parm_to_defparam_list(const string¶m)
|
||||
|
||||
// Is it a decimal number?
|
||||
num = (value[0] == '-') ? value + 1 : value;
|
||||
if (is_dec_digit_str(num)) {
|
||||
if (num[0] != '\0' && is_dec_digit_str(num)) {
|
||||
verinum *val = make_unsized_dec(num);
|
||||
if (value[0] == '-') *val = -(*val);
|
||||
PExpr* ndec = new PENumber(val);
|
||||
|
||||
+1
-1
@@ -109,7 +109,7 @@ void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net)
|
||||
return;
|
||||
|
||||
list<perm_string>*this_name = new list<perm_string>;
|
||||
this_name->push_back(perm_string::literal("@"));
|
||||
this_name->push_back(perm_string::literal(THIS_TOKEN));
|
||||
vector<pform_tf_port_t>*this_port = pform_make_task_ports(loc,
|
||||
NetNet::PINPUT,
|
||||
pform_cur_class->type,
|
||||
|
||||
@@ -381,6 +381,14 @@ inline perm_string peek_tail_name(const pform_name_t&that)
|
||||
return that.back().name;
|
||||
}
|
||||
|
||||
/*
|
||||
* In pform names, the "super" and "this" keywords are converted to
|
||||
* These tokens so that they don't interfere with the namespace and
|
||||
* are handled specially.
|
||||
*/
|
||||
# define SUPER_TOKEN "#"
|
||||
# define THIS_TOKEN "@"
|
||||
|
||||
extern std::ostream& operator<< (std::ostream&out, const pform_name_t&);
|
||||
extern std::ostream& operator<< (std::ostream&out, const name_component_t&that);
|
||||
extern std::ostream& operator<< (std::ostream&out, const index_component_t&that);
|
||||
|
||||
+30
-6
@@ -954,7 +954,7 @@ static int show_stmt_assign_darray_pattern(ivl_statement_t net)
|
||||
|
||||
// FIXME: At the moment we reallocate the array space.
|
||||
// This probably should be a resize to avoid values glitching
|
||||
/* Allocate at least enough space for the array patter. */
|
||||
/* Allocate at least enough space for the array pattern. */
|
||||
fprintf(vvp_out, " %%ix/load %u, %u, 0;\n", size_reg, ivl_expr_parms(rval));
|
||||
/* This can not have have a X/Z value so clear flag 4. */
|
||||
fprintf(vvp_out, " %%flag_set/imm 4, 0;\n");
|
||||
@@ -1038,12 +1038,36 @@ static int show_stmt_assign_sig_darray(ivl_statement_t net)
|
||||
elements of the l-value. */
|
||||
errors += show_stmt_assign_darray_pattern(net);
|
||||
|
||||
} else {
|
||||
/* There is no l-value mux, so this must be an
|
||||
assignment to the array as a whole. Evaluate the
|
||||
"object", and store the evaluated result. */
|
||||
} else if (ivl_expr_type(rval) == IVL_EX_NEW) {
|
||||
// There is no l-value mux, and the r-value expression is
|
||||
// a "new" expression. Handle this by simply storing the
|
||||
// new object to the lval.
|
||||
errors += draw_eval_object(rval);
|
||||
fprintf(vvp_out, " %%store/obj v%p_0;\n", var);
|
||||
fprintf(vvp_out, " %%store/obj v%p_0; %s:%u: %s = new ...\n",
|
||||
var, ivl_stmt_file(net), ivl_stmt_lineno(net),
|
||||
ivl_signal_basename(var));
|
||||
|
||||
} else if (ivl_expr_type(rval) == IVL_EX_SIGNAL) {
|
||||
|
||||
// There is no l-value mux, and the r-value expression is
|
||||
// a "signal" expression. Store a duplicate into the lvalue
|
||||
// By using the %dup/obj. Remember to pop the rvalue that
|
||||
// is no longer needed.
|
||||
errors += draw_eval_object(rval);
|
||||
fprintf(vvp_out, " %%dup/obj;\n");
|
||||
fprintf(vvp_out, " %%store/obj v%p_0; %s:%u: %s = <signal>\n",
|
||||
var, ivl_stmt_file(net), ivl_stmt_lineno(net),
|
||||
ivl_signal_basename(var));
|
||||
fprintf(vvp_out, " %%pop/obj 1, 0;\n");
|
||||
|
||||
} else {
|
||||
// There is no l-value mux, so this must be an
|
||||
// assignment to the array as a whole. Evaluate the
|
||||
// "object", and store the evaluated result.
|
||||
errors += draw_eval_object(rval);
|
||||
fprintf(vvp_out, " %%store/obj v%p_0; %s:%u: %s = <expr type %d>\n",
|
||||
var, ivl_stmt_file(net), ivl_stmt_lineno(net),
|
||||
ivl_signal_basename(var), ivl_expr_type(rval));
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
#norootforbuild
|
||||
#
|
||||
%define rev_date 20150815
|
||||
%define rev_date 20201003
|
||||
# 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
|
||||
@@ -10,7 +10,7 @@
|
||||
#
|
||||
Summary: Icarus Verilog
|
||||
Name: verilog%{suff}
|
||||
Version: 11.0.%{rev_date}
|
||||
Version: 12.0.%{rev_date}
|
||||
Release: 0
|
||||
License: GPL
|
||||
Group: Productivity/Scientific/Electronics
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
* Edit this definition in version_base.in to define the base version
|
||||
* number for the compiled result.
|
||||
*/
|
||||
# define VERSION_MAJOR 11
|
||||
# define VERSION_MAJOR 12
|
||||
# define VERSION_MINOR 0
|
||||
|
||||
/*
|
||||
|
||||
@@ -107,6 +107,7 @@ extern bool of_DISABLE_FORK(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DIV(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DIV_S(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DIV_WR(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DUP_OBJ(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DUP_REAL(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_DUP_VEC4(vthread_t thr, vvp_code_t code);
|
||||
extern bool of_END(vthread_t thr, vvp_code_t code);
|
||||
|
||||
@@ -159,6 +159,7 @@ static const struct opcode_table_s opcode_table[] = {
|
||||
{ "%div", of_DIV, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%div/s", of_DIV_S, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%div/wr", of_DIV_WR, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%dup/obj", of_DUP_OBJ, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%dup/real", of_DUP_REAL,0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%dup/vec4", of_DUP_VEC4,0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
{ "%end", of_END, 0, {OA_NONE, OA_NONE, OA_NONE} },
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; Copyright (c) 2001-2015 Stephen Williams ([email protected])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:ivl_version "11.0" "vec4-stack";
|
||||
:ivl_version "12.0" "vec4-stack";
|
||||
:vpi_module "system";
|
||||
|
||||
; This program is free software; you can redistribute it and/or modify
|
||||
|
||||
+3
-2
@@ -491,8 +491,9 @@ This opcode divides the left operand by the right operand. If the
|
||||
right operand is 0, then the result is NaN.
|
||||
|
||||
|
||||
* dup/real
|
||||
* dup/vec4
|
||||
* %dup/real
|
||||
* %dup/vec4
|
||||
* %dup/obj
|
||||
|
||||
These opcodes duplicate the value on the top of the stack for the
|
||||
corresponding type.
|
||||
|
||||
@@ -3002,6 +3002,19 @@ bool of_DIV_WR(vthread_t thr, vvp_code_t)
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* %dup/obj
|
||||
* %dup/real
|
||||
* %dup/vec4
|
||||
*
|
||||
* Push a duplicate of the object on the appropriate stack.
|
||||
*/
|
||||
bool of_DUP_OBJ(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
thr->push_object(thr->peek_object().duplicate());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool of_DUP_REAL(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
thr->push_real(thr->peek_real(0));
|
||||
@@ -5596,6 +5609,17 @@ bool of_RETLOAD_VEC4(vthread_t thr, vvp_code_t cp)
|
||||
return retload<vvp_vector4_t>(thr, cp);
|
||||
}
|
||||
|
||||
/*
|
||||
* %scopy
|
||||
*
|
||||
* Pop the top item from the object stack, and shallow_copy() that item into
|
||||
* the new top of the object stack. This will copy at many items as needed
|
||||
* from the source object to fill the target object. If the target object is
|
||||
* larger then the source object, then some items will be left unchanged.
|
||||
*
|
||||
* The object may be any kind of object that supports shallow_copy(),
|
||||
* including dynamic arrays and class objects.
|
||||
*/
|
||||
bool of_SCOPY(vthread_t thr, vvp_code_t)
|
||||
{
|
||||
vvp_object_t tmp;
|
||||
|
||||
+48
-86
@@ -67,11 +67,6 @@ void vvp_darray::get_word(unsigned, vvp_object_t&)
|
||||
cerr << "XXXX get_word(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
void vvp_darray::shallow_copy(const vvp_object*)
|
||||
{
|
||||
cerr << "XXXX shallow_copy(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_darray::get_bitstream(bool)
|
||||
{
|
||||
cerr << "XXXX get_bitstream() not implemented for " << typeid(*this).name() << endl;
|
||||
@@ -122,6 +117,15 @@ template <class TYPE> void vvp_darray_atom<TYPE>::shallow_copy(const vvp_object*
|
||||
array_[idx] = that->array_[idx];
|
||||
}
|
||||
|
||||
template <class TYPE> vvp_object* vvp_darray_atom<TYPE>::duplicate(void) const
|
||||
{
|
||||
vvp_darray_atom<TYPE>*that = new vvp_darray_atom<TYPE>(array_.size());
|
||||
for (size_t idx = 0 ; idx < array_.size() ; idx += 1)
|
||||
that->array_[idx] = array_[idx];
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
template <class TYPE> vvp_vector4_t vvp_darray_atom<TYPE>::get_bitstream(bool)
|
||||
{
|
||||
const unsigned word_wid = sizeof(TYPE) * 8;
|
||||
@@ -192,6 +196,16 @@ void vvp_darray_vec4::shallow_copy(const vvp_object*obj)
|
||||
array_[idx] = that->array_[idx];
|
||||
}
|
||||
|
||||
vvp_object* vvp_darray_vec4::duplicate(void) const
|
||||
{
|
||||
vvp_darray_vec4*that = new vvp_darray_vec4(array_.size(), word_wid_);
|
||||
|
||||
for (size_t idx = 0 ; idx < array_.size() ; idx += 1)
|
||||
that->array_[idx] = array_[idx];
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_darray_vec4::get_bitstream(bool as_vec4)
|
||||
{
|
||||
vvp_vector4_t vec(array_.size() * word_wid_, BIT4_0);
|
||||
@@ -344,6 +358,16 @@ void vvp_darray_real::shallow_copy(const vvp_object*obj)
|
||||
array_[idx] = that->array_[idx];
|
||||
}
|
||||
|
||||
vvp_object* vvp_darray_real::duplicate(void) const
|
||||
{
|
||||
vvp_darray_real*that = new vvp_darray_real(array_.size());
|
||||
|
||||
for (size_t idx = 0 ; idx < array_.size() ; idx += 1)
|
||||
that->array_[idx] = array_[idx];
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
vvp_vector4_t vvp_darray_real::get_bitstream(bool)
|
||||
{
|
||||
const unsigned word_wid = sizeof(double) * 8;
|
||||
@@ -406,6 +430,16 @@ void vvp_darray_string::shallow_copy(const vvp_object*obj)
|
||||
array_[idx] = that->array_[idx];
|
||||
}
|
||||
|
||||
vvp_object* vvp_darray_string::duplicate(void) const
|
||||
{
|
||||
vvp_darray_string*that = new vvp_darray_string(array_.size());
|
||||
|
||||
for (size_t idx = 0 ; idx < array_.size() ; idx += 1)
|
||||
that->array_[idx] = array_[idx];
|
||||
|
||||
return that;
|
||||
}
|
||||
|
||||
vvp_queue::~vvp_queue()
|
||||
{
|
||||
}
|
||||
@@ -591,22 +625,7 @@ void vvp_queue_real::insert(unsigned idx, double value, unsigned max_size)
|
||||
<< max_size << "]." << endl;
|
||||
queue.pop_back();
|
||||
}
|
||||
// Inserting at the beginning
|
||||
if (idx == 0)
|
||||
queue.push_front(value);
|
||||
// Inserting in the middle
|
||||
else {
|
||||
std::deque<double>::iterator pos;
|
||||
unsigned middle = queue.size()/2;
|
||||
if (idx < middle) {
|
||||
pos = queue.begin();
|
||||
for (unsigned count = 0; count < idx; ++count) ++pos;
|
||||
} else {
|
||||
pos = queue.end();
|
||||
for (unsigned count = queue.size(); count > idx; --count) --pos;
|
||||
}
|
||||
queue.insert(pos, value);
|
||||
}
|
||||
queue.insert(queue.begin()+idx, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,17 +654,8 @@ void vvp_queue_real::push_front(double value, unsigned max_size)
|
||||
|
||||
void vvp_queue_real::erase(unsigned idx)
|
||||
{
|
||||
std::deque<double>::iterator pos;
|
||||
unsigned middle = queue.size()/2;
|
||||
if (idx < middle) {
|
||||
pos = queue.begin();
|
||||
for (unsigned count = 0; count < idx; ++count) ++pos;
|
||||
} else {
|
||||
pos = queue.end();
|
||||
for (unsigned count = queue.size(); count > idx; --count) --pos;
|
||||
}
|
||||
|
||||
queue.erase(pos);
|
||||
assert(queue.size() > idx);
|
||||
queue.erase(queue.begin()+idx);
|
||||
}
|
||||
|
||||
void vvp_queue_real::erase_tail(unsigned idx)
|
||||
@@ -727,22 +737,7 @@ void vvp_queue_string::insert(unsigned idx, const string&value, unsigned max_siz
|
||||
<< max_size << "]." << endl;
|
||||
queue.pop_back();
|
||||
}
|
||||
// Inserting at the beginning
|
||||
if (idx == 0)
|
||||
queue.push_front(value);
|
||||
// Inserting in the middle
|
||||
else {
|
||||
std::deque<string>::iterator pos;
|
||||
unsigned middle = queue.size()/2;
|
||||
if (idx < middle) {
|
||||
pos = queue.begin();
|
||||
for (unsigned count = 0; count < idx; ++count) ++pos;
|
||||
} else {
|
||||
pos = queue.end();
|
||||
for (unsigned count = queue.size(); count > idx; --count) --pos;
|
||||
}
|
||||
queue.insert(pos, value);
|
||||
}
|
||||
queue.insert(queue.begin()+idx, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -771,17 +766,8 @@ void vvp_queue_string::push_front(const string&value, unsigned max_size)
|
||||
|
||||
void vvp_queue_string::erase(unsigned idx)
|
||||
{
|
||||
std::deque<std::string>::iterator pos;
|
||||
unsigned middle = queue.size()/2;
|
||||
if (idx < middle) {
|
||||
pos = queue.begin();
|
||||
for (unsigned count = 0; count < idx; ++count) ++pos;
|
||||
} else {
|
||||
pos = queue.end();
|
||||
for (unsigned count = queue.size(); count > idx; --count) --pos;
|
||||
}
|
||||
|
||||
queue.erase(pos);
|
||||
assert(queue.size() > idx);
|
||||
queue.erase(queue.begin()+idx);
|
||||
}
|
||||
|
||||
void vvp_queue_string::erase_tail(unsigned idx)
|
||||
@@ -863,22 +849,7 @@ void vvp_queue_vec4::insert(unsigned idx, const vvp_vector4_t&value, unsigned ma
|
||||
<< value.size() << "]> [" << max_size << "]." << endl;
|
||||
queue.pop_back();
|
||||
}
|
||||
// Inserting at the beginning
|
||||
if (idx == 0)
|
||||
queue.push_front(value);
|
||||
// Inserting in the middle
|
||||
else {
|
||||
std::deque<vvp_vector4_t>::iterator pos;
|
||||
unsigned middle = queue.size()/2;
|
||||
if (idx < middle) {
|
||||
pos = queue.begin();
|
||||
for (unsigned count = 0; count < idx; ++count) ++pos;
|
||||
} else {
|
||||
pos = queue.end();
|
||||
for (unsigned count = queue.size(); count > idx; --count) --pos;
|
||||
}
|
||||
queue.insert(pos, value);
|
||||
}
|
||||
queue.insert(queue.begin()+idx, value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -907,17 +878,8 @@ void vvp_queue_vec4::push_front(const vvp_vector4_t&value, unsigned max_size)
|
||||
|
||||
void vvp_queue_vec4::erase(unsigned idx)
|
||||
{
|
||||
std::deque<vvp_vector4_t>::iterator pos;
|
||||
unsigned middle = queue.size()/2;
|
||||
if (idx < middle) {
|
||||
pos = queue.begin();
|
||||
for (unsigned count = 0; count < idx; ++count) ++pos;
|
||||
} else {
|
||||
pos = queue.end();
|
||||
for (unsigned count = queue.size(); count > idx; --count) --pos;
|
||||
}
|
||||
|
||||
queue.erase(pos);
|
||||
assert(queue.size() > idx);
|
||||
queue.erase(queue.begin()+idx);
|
||||
}
|
||||
|
||||
void vvp_queue_vec4::erase_tail(unsigned idx)
|
||||
|
||||
+5
-2
@@ -45,8 +45,6 @@ class vvp_darray : public vvp_object {
|
||||
virtual void set_word(unsigned adr, const vvp_object_t&value);
|
||||
virtual void get_word(unsigned adr, vvp_object_t&value);
|
||||
|
||||
virtual void shallow_copy(const vvp_object*obj);
|
||||
|
||||
virtual vvp_vector4_t get_bitstream(bool as_vec4);
|
||||
};
|
||||
|
||||
@@ -60,6 +58,7 @@ template <class TYPE> class vvp_darray_atom : public vvp_darray {
|
||||
void set_word(unsigned adr, const vvp_vector4_t&value);
|
||||
void get_word(unsigned adr, vvp_vector4_t&value);
|
||||
void shallow_copy(const vvp_object*obj);
|
||||
vvp_object* duplicate(void) const;
|
||||
vvp_vector4_t get_bitstream(bool as_vec4);
|
||||
|
||||
private:
|
||||
@@ -77,6 +76,7 @@ class vvp_darray_vec4 : public vvp_darray {
|
||||
void set_word(unsigned adr, const vvp_vector4_t&value);
|
||||
void get_word(unsigned adr, vvp_vector4_t&value);
|
||||
void shallow_copy(const vvp_object*obj);
|
||||
vvp_object* duplicate(void) const;
|
||||
vvp_vector4_t get_bitstream(bool as_vec4);
|
||||
|
||||
private:
|
||||
@@ -112,6 +112,7 @@ class vvp_darray_real : public vvp_darray {
|
||||
void set_word(unsigned adr, double value);
|
||||
void get_word(unsigned adr, double&value);
|
||||
void shallow_copy(const vvp_object*obj);
|
||||
vvp_object* duplicate(void) const;
|
||||
vvp_vector4_t get_bitstream(bool as_vec4);
|
||||
|
||||
private:
|
||||
@@ -128,6 +129,7 @@ class vvp_darray_string : public vvp_darray {
|
||||
void set_word(unsigned adr, const std::string&value);
|
||||
void get_word(unsigned adr, std::string&value);
|
||||
void shallow_copy(const vvp_object*obj);
|
||||
vvp_object* duplicate(void) const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> array_;
|
||||
@@ -143,6 +145,7 @@ class vvp_darray_object : public vvp_darray {
|
||||
void set_word(unsigned adr, const vvp_object_t&value);
|
||||
void get_word(unsigned adr, vvp_object_t&value);
|
||||
void shallow_copy(const vvp_object*obj);
|
||||
//virtual vvp_object* duplicate(void) const;
|
||||
|
||||
private:
|
||||
std::vector<vvp_object_t> array_;
|
||||
|
||||
+9
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2013 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2020 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
|
||||
@@ -37,5 +37,13 @@ vvp_object::~vvp_object()
|
||||
|
||||
void vvp_object::shallow_copy(const vvp_object*)
|
||||
{
|
||||
cerr << "XXXX shallow_copy(vvp_object_t) not implemented for " << typeid(*this).name() << endl;
|
||||
assert(0);
|
||||
}
|
||||
|
||||
vvp_object* vvp_object::duplicate(void) const
|
||||
{
|
||||
cerr << "XXXX duplicate() not implemented for " << typeid(*this).name() << endl;
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
+5
-1
@@ -1,7 +1,7 @@
|
||||
#ifndef IVL_vvp_object_H
|
||||
#define IVL_vvp_object_H
|
||||
/*
|
||||
* Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2012-2020 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
|
||||
@@ -33,6 +33,7 @@ class vvp_object {
|
||||
virtual ~vvp_object() =0;
|
||||
|
||||
virtual void shallow_copy(const vvp_object*that);
|
||||
virtual vvp_object* duplicate(void) const;
|
||||
|
||||
static void cleanup(void);
|
||||
|
||||
@@ -63,6 +64,9 @@ class vvp_object_t {
|
||||
|
||||
inline void shallow_copy(const vvp_object_t&that)
|
||||
{ ref_->shallow_copy(that.ref_); }
|
||||
inline vvp_object_t duplicate(void) const
|
||||
{ return vvp_object_t(ref_->duplicate()); }
|
||||
|
||||
template <class T> T*peek(void) const;
|
||||
|
||||
private:
|
||||
|
||||
Reference in New Issue
Block a user