[Libre-soc-bugs] [Bug 665] very basic nmigen-to-c compiler needed

bugzilla-daemon at libre-soc.org bugzilla-daemon at libre-soc.org
Tue Aug 31 21:48:22 BST 2021


https://bugs.libre-soc.org/show_bug.cgi?id=665

--- Comment #7 from Jacob Lifshay <programmerjake at gmail.com> ---
(In reply to Luke Kenneth Casson Leighton from comment #5)
> (In reply to Jacob Lifshay from comment #4)
> 
> > I'd expect that it'll work better for the C to be completely
> > de-generic-ified, and not use a mountain of undecipherable macros to make
> > everything work, being able to read the generated code would be nice :)
> 
> signals unfortunately are not limited in length in any way, shape or form.
> there is no such concept in c as a basic integer type capable of adding
> 4,096 bits.
> 
> consequently, macros (or macros hiding functions) are unavoidable.

there's an easy solution: use arrays when signals are more than 64-bits:

typedef uint32_t signal_word_t;
typedef uint64_t signal_dword_t;
#define SIGNAL_WORD_BITS 32
#define SIGNAL_ARRAY_SIZE(bits) \
    (((size_t)(bits) + (SIGNAL_WORD_BITS - 1)) / SIGNAL_WORD_BITS)

static inline size_t saturating_sub(size_t a, size_t b)
{
    return a >= b ? a - b : 0;
}

static inline void add_signal(
    signal_word_t *restrict out,
    const signal_word_t *in0,
    const signal_word_t *in1,
    size_t bits)
{
    size_t i;
    signal_dword_t carry = 0;
    for(i = 0; bits > 0; i++)
    {
        signal_dword_t sum = (signal_dword_t)in0[i];
        sum += (signal_dword_t)in1[i] + carry;
        carry = sum >> SIGNAL_WORD_BITS;
        if(bits < SIGNAL_WORD_BITS)
            sum &= (1ULL << bits) - 1;
        out[i] = (signal_word_t)sum;
        bits = saturating_sub(bits, SIGNAL_WORD_BITS);
    }
}

void cast_unsigned_signal(
    signal_word_t *restrict out,
    size_t out_bits,
    const signal_word_t *in,
    size_t in_bits)
{
    size_t i;
    for(i = 0; out_bits > 0; i++)
    {
        signal_word_t v = in_bits > 0 ? in[i] : 0;
        // assumption: `in` is already padded with zero bits
        // to fill out the last word
        if(out_bits < SIGNAL_WORD_BITS)
            v &= (1ULL << out_bits) - 1;
        out[i] = v;
        out_bits = saturating_sub(out_bits, SIGNAL_WORD_BITS);
        in_bits = saturating_sub(in_bits, SIGNAL_WORD_BITS);
    }
}

void openpower_add(openpower_regs *regs) {
    // replace with actual code:
    signal_word_t ra[SIGNAL_ARRAY_SIZE(64)];
    signal_word_t rb[SIGNAL_ARRAY_SIZE(64)];
    signal_word_t rt[SIGNAL_ARRAY_SIZE(64)];
    signal_word_t lhs[SIGNAL_ARRAY_SIZE(256)];
    signal_word_t rhs[SIGNAL_ARRAY_SIZE(256)];
    signal_word_t sum[SIGNAL_ARRAY_SIZE(256)];
    ra[0] = (signal_word_t)regs.ra;
    ra[1] = regs.ra >> SIGNAL_WORD_BITS;
    rb[0] = (signal_word_t)regs.rb;
    rb[1] = regs.rb >> SIGNAL_WORD_BITS;
    cast_unsigned_signal(lhs, 256, ra, 64);
    cast_unsigned_signal(rhs, 256, rb, 64);
    add_signal(sum, lhs, rhs, 256);
    cast_unsigned_signal(rt, 64, sum, 256);
    regs.rt = ((signal_dword_t)rt[1] << SIGNAL_WORD_BITS) | rt[0];
}

-- 
You are receiving this mail because:
You are on the CC list for the bug.


More information about the libre-soc-bugs mailing list