Skip to content

Commit

Permalink
Replace "convstr" opcode with a pure VHDL implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
nickg committed Aug 20, 2023
1 parent c3e1ed7 commit 460342e
Show file tree
Hide file tree
Showing 16 changed files with 110 additions and 115 deletions.
33 changes: 33 additions & 0 deletions lib/nvc/text_util-body.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -395,4 +395,37 @@ package body text_util is
return fraction;
end if;
end function;

function change_bounds (s : string; l, r : positive) return string is
alias ss : string(l to r) is s;
begin
return ss;
end function;

function int_to_string (x : t_int64) return string is
variable tmp : t_int64 := x;
variable buf : string(1 to 32);
variable pos : positive := buf'right;
constant zero : natural := character'pos('0');
begin
loop
buf(pos) := character'val(zero + integer(abs(tmp rem 10)));
pos := pos - 1;
tmp := tmp / 10;
exit when tmp = 0;
end loop;
if x < 0 then
buf(pos) := '-';
pos := pos - 1;
end if;
return change_bounds(buf(pos + 1 to buf'right), 1, buf'right - pos);
end function;

function real_to_string (x : real) return string is
function impl (x : real) return string;
attribute foreign of impl : function is "_std_to_string_real";
begin
return impl(x);
end function;

end package body;
2 changes: 2 additions & 0 deletions lib/nvc/text_util.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ package text_util is
procedure string_to_int (s : in string; value : out t_int64;
used : out natural);
function string_to_real (s : string) return real;
function int_to_string (x : t_int64) return string;
function real_to_string (x : real) return string;

-- Used to implement 'VALUE for composite types
function next_delimiter (s : string; pos : natural) return string;
Expand Down
21 changes: 10 additions & 11 deletions src/jit/jit-dump.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,16 @@ const char *jit_exit_name(jit_exit_t exit)
{
static const char *names[] = {
"INDEX_FAIL", "OVERFLOW", "NULL_DEREF", "LENGTH_FAIL", "UNREACHABLE",
"DIV_ZERO", "EXPONENT_FAIL", "REPORT", "ASSERT_FAIL", "INT_TO_STRING",
"REAL_TO_STRING", "RANGE_FAIL", "FUNC_WAIT", "INIT_SIGNAL",
"DRIVE_SIGNAL", "SCHED_WAVEFORM", "SCHED_PROCESS", "TEST_EVENT",
"TEST_ACTIVE", "SCHED_EVENT", "FILE_OPEN", "FILE_CLOSE",
"FILE_READ", "FILE_WRITE", "ENDFILE", "DEBUG_OUT", "ALIAS_SIGNAL",
"MAP_SIGNAL", "MAP_CONST", "RESOLVE_SIGNAL", "LAST_EVENT",
"LAST_ACTIVE", "DISCONNECT", "ELAB_ORDER_FAIL", "FORCE", "RELEASE",
"PUSH_SCOPE", "POP_SCOPE", "IMPLICIT_SIGNAL", "DRIVING", "DRIVING_VALUE",
"CLAIM_TLAB", "COVER_TOGGLE", "PROCESS_INIT", "CLEAR_EVENT",
"IMPLICIT_EVENT", "ENTER_STATE", "REFLECT_VALUE", "REFLECT_SUBTYPE",
"FUNCTION_TRIGGER", "ADD_TRIGGER",
"DIV_ZERO", "EXPONENT_FAIL", "REPORT", "ASSERT_FAIL", "RANGE_FAIL",
"FUNC_WAIT", "INIT_SIGNAL", "DRIVE_SIGNAL", "SCHED_WAVEFORM",
"SCHED_PROCESS", "TEST_EVENT", "TEST_ACTIVE", "SCHED_EVENT",
"FILE_OPEN", "FILE_CLOSE","FILE_READ", "FILE_WRITE", "ENDFILE",
"DEBUG_OUT", "ALIAS_SIGNAL", "MAP_SIGNAL", "MAP_CONST", "RESOLVE_SIGNAL",
"LAST_EVENT", "LAST_ACTIVE", "DISCONNECT", "ELAB_ORDER_FAIL", "FORCE",
"RELEASE", "PUSH_SCOPE", "POP_SCOPE", "IMPLICIT_SIGNAL", "DRIVING",
"DRIVING_VALUE", "CLAIM_TLAB", "COVER_TOGGLE", "PROCESS_INIT",
"CLEAR_EVENT", "IMPLICIT_EVENT", "ENTER_STATE", "REFLECT_VALUE",
"REFLECT_SUBTYPE", "FUNCTION_TRIGGER", "ADD_TRIGGER",
};
assert(exit < ARRAY_LEN(names));
return names[exit];
Expand Down
38 changes: 0 additions & 38 deletions src/jit/jit-exits.c
Original file line number Diff line number Diff line change
Expand Up @@ -309,18 +309,6 @@ void x_div_zero(tree_t where)
jit_msg(tree_loc(where), DIAG_FATAL, "division by zero");
}

ffi_uarray_t x_int_to_string(int64_t value, char *buf, size_t max)
{
size_t len = checked_sprintf(buf, max, "%"PRIi64, value);
return ffi_wrap(buf, 1, len);
}

ffi_uarray_t x_real_to_string(double value, char *buf, size_t max)
{
size_t len = checked_sprintf(buf, max, "%.*g", DBL_DIG, value);
return ffi_wrap(buf, 1, len);
}

void x_elab_order_fail(tree_t where)
{
assert(tree_kind(where) == T_EXTERNAL_NAME);
Expand Down Expand Up @@ -601,19 +589,6 @@ void __nvc_do_exit(jit_exit_t which, jit_anchor_t *anchor, jit_scalar_t *args,
}
break;

case JIT_EXIT_INT_TO_STRING:
{
int64_t value = args[0].integer;

char *buf = jit_mspace_alloc(28);

ffi_uarray_t u = x_int_to_string(value, buf, 28);
args[0].pointer = u.ptr;
args[1].integer = u.dims[0].left;
args[2].integer = u.dims[0].length;
}
break;

case JIT_EXIT_ALIAS_SIGNAL:
{
if (!jit_has_runtime(jit_thread_local()->jit))
Expand All @@ -626,19 +601,6 @@ void __nvc_do_exit(jit_exit_t which, jit_anchor_t *anchor, jit_scalar_t *args,
}
break;

case JIT_EXIT_REAL_TO_STRING:
{
double value = args[0].real;

char *buf = jit_mspace_alloc(32);

ffi_uarray_t u = x_real_to_string(value, buf, 32);
args[0].pointer = u.ptr;
args[1].integer = u.dims[0].left;
args[2].integer = u.dims[0].length;
}
break;

case JIT_EXIT_DISCONNECT:
{
sig_shared_t *shared = args[0].pointer;
Expand Down
2 changes: 0 additions & 2 deletions src/jit/jit-exits.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ void x_exponent_fail(int64_t value, tree_t where);
void x_overflow(int64_t lhs, int64_t rhs, tree_t where);
void x_null_deref(tree_t where);
void x_div_zero(tree_t where);
ffi_uarray_t x_int_to_string(int64_t value, char *buf, size_t max);
ffi_uarray_t x_real_to_string(double value, char *buf, size_t max);
void x_assert_fail(const uint8_t *msg, int32_t msg_len, int8_t severity,
int64_t hint_left, int64_t hint_right, int8_t hint_valid,
object_t *where);
Expand Down
26 changes: 0 additions & 26 deletions src/jit/jit-irgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -3267,29 +3267,6 @@ static void irgen_op_active(jit_irgen_t *g, int op)
g->map[vcode_get_result(op)] = j_recv(g, 0);
}

static void irgen_op_convstr(jit_irgen_t *g, int op)
{
jit_value_t value = irgen_get_arg(g, op, 0);

j_send(g, 0, value);

switch (vcode_reg_kind(vcode_get_arg(op, 0))) {
case VCODE_TYPE_INT:
macro_exit(g, JIT_EXIT_INT_TO_STRING);
break;
case VCODE_TYPE_REAL:
macro_exit(g, JIT_EXIT_REAL_TO_STRING);
break;
default:
vcode_dump_with_mark(op, NULL, NULL);
fatal_trace("invalid type in convstr");
}

g->map[vcode_get_result(op)] = j_recv(g, 0);
j_recv(g, 1); // Left
j_recv(g, 2); // Length
}

static void irgen_op_debug_out(jit_irgen_t *g, int op)
{
jit_value_t value = irgen_get_arg(g, op, 0);
Expand Down Expand Up @@ -3806,9 +3783,6 @@ static void irgen_block(jit_irgen_t *g, vcode_block_t block)
case VCODE_OP_CLEAR_EVENT:
irgen_op_clear_event(g, i);
break;
case VCODE_OP_CONVSTR:
irgen_op_convstr(g, i);
break;
case VCODE_OP_DEBUG_OUT:
irgen_op_debug_out(g, i);
break;
Expand Down
2 changes: 0 additions & 2 deletions src/jit/jit-priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,6 @@ typedef enum {
JIT_EXIT_EXPONENT_FAIL,
JIT_EXIT_REPORT,
JIT_EXIT_ASSERT_FAIL,
JIT_EXIT_INT_TO_STRING,
JIT_EXIT_REAL_TO_STRING,
JIT_EXIT_RANGE_FAIL,
JIT_EXIT_FUNC_WAIT,
JIT_EXIT_INIT_SIGNAL,
Expand Down
48 changes: 42 additions & 6 deletions src/lower.c
Original file line number Diff line number Diff line change
Expand Up @@ -7903,10 +7903,23 @@ static void lower_enum_image_helper(type_t type, vcode_reg_t preg)
}
}

static void lower_physical_image_helper(type_t type, vcode_reg_t preg)
static void lower_physical_image_helper(lower_unit_t *lu, type_t type,
vcode_reg_t preg)
{
vcode_type_t vint64 = vtype_int(INT64_MIN, INT64_MAX);
vcode_reg_t num_reg = emit_convstr(emit_cast(vint64, vint64, preg));
vcode_type_t vchar = vtype_char();
vcode_type_t vstring = vtype_uarray(1, vchar, vchar);

vcode_reg_t cast_reg = emit_cast(vint64, vint64, preg);
ident_t conv_fn =
ident_new("NVC.TEXT_UTIL.INT_TO_STRING(21NVC.TEXT_UTIL.T_INT64)S");
vcode_reg_t conv_args[] = {
lower_context_for_call(lu, conv_fn),
cast_reg
};
vcode_reg_t num_reg = emit_fcall(conv_fn, vstring, vstring,
VCODE_CC_VHDL, conv_args, 2);

vcode_reg_t num_len = emit_uarray_len(num_reg, 0);

const char *unit0 = istr(ident_downcase(tree_ident(type_unit(type, 0))));
Expand Down Expand Up @@ -7936,9 +7949,32 @@ static void lower_physical_image_helper(type_t type, vcode_reg_t preg)
emit_return(emit_wrap(mem_reg, dims, 1));
}

static void lower_numeric_image_helper(type_t type, vcode_reg_t preg)
static void lower_numeric_image_helper(lower_unit_t *lu, type_t type,
vcode_reg_t preg)
{
vcode_reg_t str_reg = emit_convstr(preg);
vcode_type_t vchar = vtype_char();
vcode_type_t vstring = vtype_uarray(1, vchar, vchar);

ident_t conv_fn;
vcode_reg_t arg_reg;

if (type_is_real(type)) {
arg_reg = preg;
conv_fn = ident_new("NVC.TEXT_UTIL.REAL_TO_STRING(R)S");
}
else {
vcode_type_t vint64 = vtype_int(INT64_MIN, INT64_MAX);
arg_reg = emit_cast(vint64, vint64, preg);
conv_fn = ident_new(
"NVC.TEXT_UTIL.INT_TO_STRING(21NVC.TEXT_UTIL.T_INT64)S");
}

vcode_reg_t conv_args[] = {
lower_context_for_call(lu, conv_fn),
arg_reg
};
vcode_reg_t str_reg = emit_fcall(conv_fn, vstring, vstring,
VCODE_CC_VHDL, conv_args, 2);
emit_return(str_reg);
}

Expand Down Expand Up @@ -8224,10 +8260,10 @@ static void lower_image_helper(lower_unit_t *lu, object_t *obj)
break;
case T_INTEGER:
case T_REAL:
lower_numeric_image_helper(type, preg);
lower_numeric_image_helper(lu, type, preg);
break;
case T_PHYSICAL:
lower_physical_image_helper(type, preg);
lower_physical_image_helper(lu, type, preg);
break;
case T_RECORD:
lower_record_image_helper(lu, type, preg);
Expand Down
2 changes: 1 addition & 1 deletion src/rt/rt.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@

#include <stdint.h>

#define RT_ABI_VERSION 19
#define RT_ABI_VERSION 20
#define RT_ALIGN_MASK 0x7
#define RT_MULTITHREADED 0

Expand Down
9 changes: 9 additions & 0 deletions src/rt/standard.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,15 @@ void _std_to_ostring_bit_vec(const uint8_t *vec_ptr, int64_t vec_len,
*u = bit_vec_to_string(vec_ptr, vec_len, 3);
}

DLLEXPORT
void _std_to_string_real(double value, ffi_uarray_t *u)
{
const size_t max = 32;
char *buf = jit_mspace_alloc(max);
size_t len = checked_sprintf(buf, max, "%.*g", DBL_DIG, value);
*u = ffi_wrap(buf, 1, len);
}

void _std_standard_init(void)
{
// Dummy function to force linking
Expand Down
1 change: 1 addition & 0 deletions src/symbols.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
_std_standard_now;
_std_to_hstring_bit_vec;
_std_to_ostring_bit_vec;
_std_to_string_real;
_std_to_string_real_digits;
_std_to_string_real_format;
_std_to_string_time;
Expand Down
29 changes: 3 additions & 26 deletions src/vcode.c
Original file line number Diff line number Diff line change
Expand Up @@ -420,10 +420,6 @@ void vcode_heap_allocate(vcode_reg_t reg)
// Returns a pointer into the C heap
break;

case VCODE_OP_CONVSTR:
// Runtime code allocates in mspace
break;

case VCODE_OP_LOAD:
{
if (vcode_reg_kind(reg) != VCODE_TYPE_UARRAY)
Expand Down Expand Up @@ -961,10 +957,9 @@ const char *vcode_op_string(vcode_op_t op)
"range length", "exponent check", "zero check", "map const",
"resolve signal", "push scope", "pop scope", "alias signal", "trap add",
"trap sub", "trap mul", "force", "release", "link instance",
"unreachable", "package init", "canon value", "convstr",
"trap neg", "process init", "clear event", "trap exp", "implicit event",
"enter state", "reflect value", "reflect subtype", "function trigger",
"add trigger",
"unreachable", "package init", "trap neg", "process init", "clear event",
"trap exp", "implicit event", "enter state", "reflect value",
"reflect subtype", "function trigger", "add trigger",
};
if ((unsigned)op >= ARRAY_LEN(strs))
return "???";
Expand Down Expand Up @@ -1659,7 +1654,6 @@ void vcode_dump_with_mark(int mark_op, vcode_dump_fn_t callback, void *arg)
break;

case VCODE_OP_NOT:
case VCODE_OP_CONVSTR:
{
col += vcode_dump_reg(op->result);
col += printf(" := %s ", vcode_op_string(op->kind));
Expand Down Expand Up @@ -5660,23 +5654,6 @@ vcode_reg_t emit_undefined(vcode_type_t type, vcode_type_t bounds)
return op->result;
}

vcode_reg_t emit_convstr(vcode_reg_t value)
{
VCODE_FOR_EACH_MATCHING_OP(other, VCODE_OP_CONVSTR) {
if (other->args.items[0] == value)
return other->result;
}

op_t *op = vcode_add_op(VCODE_OP_CONVSTR);
vcode_add_arg(op, value);

VCODE_ASSERT(vtype_is_scalar(vcode_reg_type(value)),
"convstr value must be scalar");

vcode_type_t vchar = vtype_char();
return (op->result = vcode_add_reg(vtype_uarray(1, vchar, vchar)));
}

void emit_debug_info(const loc_t *loc)
{
if (!loc_invalid_p(loc))
Expand Down
2 changes: 0 additions & 2 deletions src/vcode.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,6 @@ typedef enum {
VCODE_OP_LINK_INSTANCE,
VCODE_OP_UNREACHABLE,
VCODE_OP_PACKAGE_INIT,
VCODE_OP_CONVSTR,
VCODE_OP_TRAP_NEG,
VCODE_OP_PROCESS_INIT,
VCODE_OP_CLEAR_EVENT,
Expand Down Expand Up @@ -513,7 +512,6 @@ void emit_push_scope(vcode_reg_t locus, vcode_type_t type);
void emit_pop_scope(void);
void emit_alias_signal(vcode_reg_t signal, vcode_reg_t locus);
void emit_unreachable(vcode_reg_t locus);
vcode_reg_t emit_convstr(vcode_reg_t value);
void emit_enter_state(vcode_reg_t state);
vcode_reg_t emit_reflect_value(ident_t ptype, vcode_reg_t value,
vcode_reg_t context, vcode_reg_t locus,
Expand Down
4 changes: 4 additions & 0 deletions test/regress/gold/image1.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@
1010ps+0: Report Note: a
1010ps+0: Report Note: 3
1010ps+0: Report Note: 20 unit_1
1010ps+0: Report Note: 0
1010ps+0: Report Note: 10
1010ps+0: Report Note: -2147483648
1010ps+0: Report Note: 2147483647
4 changes: 4 additions & 0 deletions test/regress/image1.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ begin
print_enum1(e1);
report my_int'image(j);
report my_phys'image(2 UNIT_2);
report integer'image(0);
report integer'image(10);
report integer'image(integer'left);
report integer'image(integer'right);
wait;
end process;

Expand Down
2 changes: 1 addition & 1 deletion test/test_simp.c
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ START_TEST(test_ffold)
fail_unless(folded_b(tree_value(tree_decl(b, 13)), true));
fail_unless(folded_b(tree_value(tree_decl(b, 14)), false));
fail_unless(folded_b(tree_value(tree_decl(b, 15)), true));
fail_unless(folded_b(tree_value(tree_decl(b, 16)), true));
fail_if(folded_b(tree_value(tree_decl(b, 16)), true)); // Cannot fold now
fail_unless(folded_b(tree_value(tree_decl(b, 17)), true));
fail_unless(folded_b(tree_value(tree_decl(b, 18)), true));
fail_unless(folded_i(tree_value(tree_decl(b, 19)), 80));
Expand Down

0 comments on commit 460342e

Please sign in to comment.