Better optimization of constants in expressions

Be more sophisticated with the code generated for constant values.
When values are large, use an optimal mix of %movi and %mov
instructions to get the desired value, no matter what the content.
This commit is contained in:
Stephen Williams 2008-08-27 18:22:23 -07:00
parent 091a546387
commit 0121c41942
1 changed files with 34 additions and 10 deletions

View File

@ -1670,22 +1670,31 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
vvp_errors += 1; vvp_errors += 1;
} }
/* Detect the special case that the entire number fits in an
immediate. In this case we generate a single %movi
instruction. */
if ((!number_is_unknown(exp)) && number_is_immediate(exp, IMM_WID,0)) { if ((!number_is_unknown(exp)) && number_is_immediate(exp, IMM_WID,0)) {
unsigned long val = get_number_immediate(exp); unsigned long val = get_number_immediate(exp);
fprintf(vvp_out, " %%movi %u, %lu, %u;\n", res.base, val, wid); fprintf(vvp_out, " %%movi %u, %lu, %u;\n", res.base, val, wid);
return res; return res;
} }
/* Use %movi as much as possible to build the value into the
destination. Use the %mov to handle the remaining general
bits. */
idx = 0; idx = 0;
unsigned long val = 0;
unsigned val_bits = 0;
unsigned val_addr = res.base;
while (idx < nwid) { while (idx < nwid) {
unsigned cnt; char src = 0;
char src = '?';
switch (bits[idx]) { switch (bits[idx]) {
case '0': case '0':
src = '0'; val_bits += 1;
break; break;
case '1': case '1':
src = '1'; val |= 1UL << val_bits;
val_bits += 1;
break; break;
case 'x': case 'x':
src = '2'; src = '2';
@ -1695,14 +1704,29 @@ static struct vector_info draw_number_expr(ivl_expr_t exp, unsigned wid)
break; break;
} }
for (cnt = 1 ; idx+cnt < nwid ; cnt += 1) if (val_bits >= IMM_WID
if (bits[idx+cnt] != bits[idx]) || (val_bits>0 && src != 0)
break; || (val_bits>0 && idx+1==nwid)) {
fprintf(vvp_out, " %%movi %u, %lu, %u;\n",
val_addr, val, val_bits);
val_addr += val_bits;
val_bits = 0;
val = 0;
}
fprintf(vvp_out, " %%mov %u, %c, %u;\n", if (src != 0) {
res.base+idx, src, cnt); assert(val_bits == 0);
unsigned cnt;
for (cnt = 1 ; idx+cnt < nwid ; cnt += 1)
if (bits[idx+cnt] != bits[idx])
break;
idx += cnt; fprintf(vvp_out, " %%mov %u, %c, %u;\n", val_addr, src, cnt);
val_addr += cnt;
idx += cnt-1;
}
idx += 1;
} }
/* Pad the number up to the expression width. */ /* Pad the number up to the expression width. */