Enable support for providing a queue maximum index

This commit is contained in:
Cary R 2020-07-17 01:30:23 -07:00
parent 2c9cce2303
commit 6ff07c1074
12 changed files with 126 additions and 61 deletions

View File

@ -232,7 +232,9 @@ ostream& netdarray_t::debug_dump(ostream&o) const
ostream& netqueue_t::debug_dump(ostream&fd) const
{
fd << "queue of " << *element_type();
fd << "queue of ";
if (max_idx_ >= 0) fd << "(maximum of " << max_idx_+1 << " elements) ";
fd << *element_type();
return fd;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2000-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2000-2020 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
@ -1094,13 +1094,35 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
}
// Special case: Detect the mark for a QUEUE
// declaration, which is the dimensions [null:<nil>].
if (use_ridx==0 && dynamic_cast<PENull*>(use_lidx)) {
// declaration, which is the dimensions [null:max_idx].
if (dynamic_cast<PENull*>(use_lidx)) {
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
vec->set_signed(get_signed());
packed_dimensions.clear();
ivl_assert(*this, netdarray==0);
netdarray = new netqueue_t(vec);
long max_idx;
if (use_ridx) {
NetExpr*tmp = elab_and_eval(des, array_type_scope, use_ridx,
-1, true);
NetEConst*cv = dynamic_cast<NetEConst*>(tmp);
if (cv == 0) {
cerr << get_fileline() << ": error: queue '" << name_
<< "' maximum size must be a constant!" << endl;
des->errors += 1;
max_idx = -1;
} else {
verinum res = cv->value();
max_idx = res.as_long();
if (max_idx < 0) {
cerr << get_fileline() << ": error: queue '"
<< name_ << "' maximum size must be positive ("
<< max_idx << ")!" << endl;
des->errors += 1;
max_idx = -1;
}
}
} else max_idx = -1;
netdarray = new netqueue_t(vec, max_idx);
continue;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2019 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
@ -252,12 +252,13 @@ ivl_type_s* uarray_type_t::elaborate_type_raw(Design*des, NetScope*scope) const
}
// Special case: if the dimension is null:nil. this is a queue.
if (cur->second==0 && dynamic_cast<PENull*>(cur->first)) {
if (dynamic_cast<PENull*>(cur->first)) {
cerr << get_fileline() << ": sorry: "
<< "SV queues inside classes are not yet supported." << endl;
des->errors += 1;
ivl_type_s*res = new netqueue_t(btype);
// FIXME: Need to set the max size if cur->second is defined
ivl_type_s*res = new netqueue_t(btype, -1);
return res;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014 Stephen Williams (steve@icarus.com)
* Copyright (c) 2014-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
@ -22,8 +22,8 @@
using namespace std;
netqueue_t::netqueue_t(ivl_type_t vec)
: netdarray_t(vec)
netqueue_t::netqueue_t(ivl_type_t vec, long max_idx)
: netdarray_t(vec), max_idx_(max_idx)
{
}

View File

@ -1,7 +1,7 @@
#ifndef IVL__netqueue_H
#define IVL__netqueue_H
/*
* Copyright (c) 2014-2015 Stephen Williams (steve@icarus.com)
* Copyright (c) 2014-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
@ -30,7 +30,7 @@
class netqueue_t : public netdarray_t {
public:
explicit netqueue_t(ivl_type_t vec);
explicit netqueue_t(ivl_type_t vec, long max_idx);
~netqueue_t();
// This is the "base_type()" virtual method of the
@ -41,10 +41,14 @@ class netqueue_t : public netdarray_t {
// A queue may have a type that is signed.
inline bool get_signed() const { return element_type()->get_signed(); }
// Use the packed width to pass the maximum index
long packed_width(void) const { return max_idx_; }
std::ostream& debug_dump(std::ostream&) const;
private:
bool test_compatibility(ivl_type_t that) const;
long max_idx_;
};
#endif

10
parse.y
View File

@ -2657,6 +2657,16 @@ variable_dimension /* IEEE1800-2005: A.2.5 */
tmp->push_back(index);
$$ = tmp;
}
| '[' '$' ':' expression ']'
{ // SystemVerilog queue with a max size
list<pform_range_t> *tmp = new list<pform_range_t>;
pform_range_t index (new PENull,$4);
if (!gn_system_verilog()) {
yyerror("error: Queue declarations require SystemVerilog.");
}
tmp->push_back(index);
$$ = tmp;
}
;
variable_lifetime

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003-2013 Stephen Williams (steve@icarus.com)
* Copyright (c) 2003-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
@ -94,9 +94,13 @@ static int get_vpi_taskfunc_signal_arg(struct args_info *result,
If I don't need to do any evaluating, then skip it as
I'll be passing the handle to the signal itself. */
if (ivl_expr_width(expr) !=
ivl_signal_width(ivl_expr_signal(expr))) {
if ((ivl_expr_width(expr) !=
ivl_signal_width(ivl_expr_signal(expr))) &&
ivl_expr_value(expr) != IVL_VT_DARRAY) {
/* This should never happen since we have IVL_EX_SELECT. */
/* For a queue (type of darray) we return the maximum
size of the queue as the signal width. */
assert(0);
return 0;
} else if (signal_is_return_value(ivl_expr_signal(expr))) {

View File

@ -1780,24 +1780,37 @@ static int show_push_frontback_method(ivl_statement_t net, bool is_front)
ivl_type_t var_type = ivl_signal_net_type(var);
assert(ivl_type_base(var_type)== IVL_VT_QUEUE);
/* The maximum index value is passed as the signal width. */
long max_size = ivl_signal_width(var) + 1;
assert(max_size >= 0);
int idx = allocate_word();
assert(idx >= 0);
/* Save the queue maximum index value to an integer register. */
fprintf(vvp_out, " %%ix/load %u, %ld, 0;\n", idx, max_size);
fprintf(vvp_out, " %%flag_set/imm 4, 0;\n");
ivl_type_t element_type = ivl_type_element(var_type);
ivl_expr_t parm1 = ivl_stmt_parm(net,1);
switch (ivl_type_base(element_type)) {
case IVL_VT_REAL:
draw_eval_real(parm1);
fprintf(vvp_out, " %%store/%s/r v%p_0;\n", type_code, var);
fprintf(vvp_out, " %%store/%s/r v%p_0, %u;\n",
type_code, var, idx);
break;
case IVL_VT_STRING:
draw_eval_string(parm1);
fprintf(vvp_out, " %%store/%s/str v%p_0;\n", type_code, var);
fprintf(vvp_out, " %%store/%s/str v%p_0, %u;\n",
type_code, var, idx);
break;
default:
draw_eval_vec4(parm1);
fprintf(vvp_out, " %%store/%s/v v%p_0, %u;\n",
type_code, var, width_of_packed_type(element_type));
fprintf(vvp_out, " %%store/%s/v v%p_0, %u, %u;\n",
type_code, var, idx,
width_of_packed_type(element_type));
break;
}
clr_word(idx);
return 0;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2001-2019 Stephen Williams (steve@icarus.com)
* Copyright (c) 2001-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
@ -278,12 +278,12 @@ static const struct opcode_table_s opcode_table[] = {
{ "%store/prop/r", of_STORE_PROP_R, 1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%store/prop/str",of_STORE_PROP_STR,1, {OA_NUMBER, OA_NONE, OA_NONE} },
{ "%store/prop/v", of_STORE_PROP_V, 2, {OA_NUMBER, OA_BIT1, OA_NONE} },
{ "%store/qb/r", of_STORE_QB_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/qb/str", of_STORE_QB_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/qb/v", of_STORE_QB_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%store/qf/r", of_STORE_QF_R, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/qf/str", of_STORE_QF_STR, 1, {OA_FUNC_PTR, OA_NONE, OA_NONE} },
{ "%store/qf/v", of_STORE_QF_V, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%store/qb/r", of_STORE_QB_R, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%store/qb/str", of_STORE_QB_STR, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%store/qb/v", of_STORE_QB_V, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%store/qf/r", of_STORE_QF_R, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%store/qf/str", of_STORE_QF_STR, 2, {OA_FUNC_PTR, OA_BIT1, OA_NONE} },
{ "%store/qf/v", of_STORE_QF_V, 3, {OA_FUNC_PTR, OA_BIT1, OA_BIT2} },
{ "%store/real", of_STORE_REAL, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },
{ "%store/reala", of_STORE_REALA, 2, {OA_ARR_PTR, OA_BIT1, OA_NONE} },
{ "%store/str", of_STORE_STR, 1, {OA_FUNC_PTR,OA_NONE, OA_NONE} },

View File

@ -5702,7 +5702,7 @@ bool of_STORE_PROP_V(vthread_t thr, vvp_code_t cp)
}
/*
* %store/qb/r <var-label>
* %store/qb/r <var-label>, <max-idx>
*/
bool of_STORE_QB_R(vthread_t, vvp_code_t)
{
@ -5711,7 +5711,7 @@ bool of_STORE_QB_R(vthread_t, vvp_code_t)
}
/*
* %store/qb/str <var-label>
* %store/qb/str <var-label>, <max-idx>
*/
bool of_STORE_QB_STR(vthread_t thr, vvp_code_t cp)
{
@ -5719,15 +5719,16 @@ bool of_STORE_QB_STR(vthread_t thr, vvp_code_t cp)
string value = thr->pop_str();
vvp_net_t*net = cp->net;
unsigned max_size = thr->words[cp->bit_idx[0]].w_int;
vvp_queue*dqueue = get_queue_object<vvp_queue_string>(thr, net);
assert(dqueue);
dqueue->push_back(value);
dqueue->push_back(value, max_size);
return true;
}
/*
* %store/qb/v <var-label>, <wid>
* %store/qb/v <var-label>, <max-idx>, <wid>
*/
bool of_STORE_QB_V(vthread_t thr, vvp_code_t cp)
{
@ -5735,20 +5736,21 @@ bool of_STORE_QB_V(vthread_t thr, vvp_code_t cp)
vvp_vector4_t value = thr->pop_vec4();
vvp_net_t*net = cp->net;
unsigned wid = cp->bit_idx[0];
unsigned max_size = thr->words[cp->bit_idx[0]].w_int;
unsigned wid = cp->bit_idx[1];
assert(value.size() == wid);
vvp_queue*dqueue = get_queue_object<vvp_queue_vec4>(thr, net);
assert(dqueue);
dqueue->push_back(value);
dqueue->push_back(value, max_size);
return true;
}
/*
* %store/qf/r <var-label>
* %store/qf/r <var-label>, <max-idx>
*/
bool of_STORE_QF_R(vthread_t, vvp_code_t)
{
@ -5757,7 +5759,7 @@ bool of_STORE_QF_R(vthread_t, vvp_code_t)
}
/*
* %store/qf/str <var-label>
* %store/qf/str <var-label>, <max-idx>
*/
bool of_STORE_QF_STR(vthread_t, vvp_code_t)
{
@ -5766,7 +5768,7 @@ bool of_STORE_QF_STR(vthread_t, vvp_code_t)
}
/*
* %store/qb/v <var-label>, <wid>
* %store/qb/v <var-label>, <max-idx>, <wid>
*/
bool of_STORE_QF_V(vthread_t thr, vvp_code_t cp)
{
@ -5774,13 +5776,14 @@ bool of_STORE_QF_V(vthread_t thr, vvp_code_t cp)
vvp_vector4_t value = thr->pop_vec4();
vvp_net_t*net = cp->net;
unsigned wid = cp->bit_idx[0];
unsigned max_size = thr->words[cp->bit_idx[0]].w_int;
unsigned wid = cp->bit_idx[1];
vvp_queue*dqueue = get_queue_object<vvp_queue_vec4>(thr, net);
assert(value.size() == wid);
assert(dqueue);
dqueue->push_front(value);
dqueue->push_front(value, max_size);
return true;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2019 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
@ -410,32 +410,32 @@ vvp_queue::~vvp_queue()
{
}
void vvp_queue::push_back(const vvp_vector4_t&)
void vvp_queue::push_back(const vvp_vector4_t&, unsigned)
{
cerr << "XXXX push_back(vvp_vector4_t) not implemented for " << typeid(*this).name() << endl;
}
void vvp_queue::push_front(const vvp_vector4_t&)
void vvp_queue::push_front(const vvp_vector4_t&, unsigned)
{
cerr << "XXXX push_front(vvp_vector4_t) not implemented for " << typeid(*this).name() << endl;
}
void vvp_queue::push_back(double)
void vvp_queue::push_back(double, unsigned)
{
cerr << "XXXX push_back(double) not implemented for " << typeid(*this).name() << endl;
}
void vvp_queue::push_front(double)
void vvp_queue::push_front(double, unsigned)
{
cerr << "XXXX push_front(double) not implemented for " << typeid(*this).name() << endl;
}
void vvp_queue::push_back(const string&)
void vvp_queue::push_back(const string&, unsigned)
{
cerr << "XXXX push_back(string) not implemented for " << typeid(*this).name() << endl;
}
void vvp_queue::push_front(const string&)
void vvp_queue::push_front(const string&, unsigned)
{
cerr << "XXXX push_front(string) not implemented for " << typeid(*this).name() << endl;
}
@ -449,9 +449,10 @@ size_t vvp_queue_string::get_size() const
return array_.size();
}
void vvp_queue_string::push_back(const string&val)
void vvp_queue_string::push_back(const string&val, unsigned max_size)
{
array_.push_back(val);
if (!max_size || (array_.size() < max_size)) array_.push_back(val);
else cerr << "Warning: value \"" << val << "\" was not added to queue." << endl;
}
void vvp_queue_string::set_word(unsigned adr, const string&value)
@ -533,13 +534,18 @@ void vvp_queue_vec4::get_word(unsigned adr, vvp_vector4_t&value)
value = *cur;
}
void vvp_queue_vec4::push_back(const vvp_vector4_t&val)
void vvp_queue_vec4::push_back(const vvp_vector4_t&val, unsigned max_size)
{
array_.push_back(val);
if (!max_size || (array_.size() < max_size)) array_.push_back(val);
else cerr << "Warning: value " << val << " was not added to queue." << endl;
}
void vvp_queue_vec4::push_front(const vvp_vector4_t&val)
void vvp_queue_vec4::push_front(const vvp_vector4_t&val, unsigned max_size)
{
if (max_size && (array_.size() == max_size)) {
cerr << "Warning: value " << array_.back() << " was removed from queue." << endl;
array_.pop_back();
}
array_.push_front(val);
}

View File

@ -1,7 +1,7 @@
#ifndef IVL_vvp_darray_H
#define IVL_vvp_darray_H
/*
* Copyright (c) 2012-2019 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
@ -154,14 +154,14 @@ class vvp_queue : public vvp_darray {
inline vvp_queue(void) { }
~vvp_queue();
virtual void push_back(const vvp_vector4_t&value);
virtual void push_front(const vvp_vector4_t&value);
virtual void push_back(const vvp_vector4_t&value, unsigned max_size);
virtual void push_front(const vvp_vector4_t&value, unsigned max_size);
virtual void push_back(double value);
virtual void push_front(double value);
virtual void push_back(double value, unsigned max_size);
virtual void push_front(double value, unsigned max_size);
virtual void push_back(const std::string&value);
virtual void push_front(const std::string&value);
virtual void push_back(const std::string&value, unsigned max_size);
virtual void push_front(const std::string&value, unsigned max_size);
virtual void pop_back(void) =0;
virtual void pop_front(void)=0;
@ -175,8 +175,8 @@ class vvp_queue_vec4 : public vvp_queue {
size_t get_size(void) const;
void set_word(unsigned adr, const vvp_vector4_t&value);
void get_word(unsigned adr, vvp_vector4_t&value);
void push_back(const vvp_vector4_t&value);
void push_front(const vvp_vector4_t&value);
void push_back(const vvp_vector4_t&value, unsigned max_size);
void push_front(const vvp_vector4_t&value, unsigned max_size);
void pop_back(void);
void pop_front(void);
@ -193,8 +193,8 @@ class vvp_queue_string : public vvp_queue {
size_t get_size(void) const;
void set_word(unsigned adr, const std::string&value);
void get_word(unsigned adr, std::string&value);
void push_back(const std::string&value);
//void push_front(const std::string&value);
void push_back(const std::string&value, unsigned max_size);
//void push_front(const std::string&value, unsigned max_size);
void pop_back(void);
void pop_front(void);