Assembly 硬件乘法运算器

Assembly 硬件乘法运算器,assembly,mips,multiplication,alu,Assembly,Mips,Multiplication,Alu,有人能指出我做错了什么吗? 对于乘法器最右边的每一位,如果遇到一位,我会在乘积的左边添加被乘数。 谢谢你的帮助 据我所知,这似乎是一个“移位和加法”乘数 右移乘法器时,必须左移被乘数。旁注:实际ALU可能执行mux/demux,而不是实际移位,但原理相同 虽然输入reg是4位的,但由于您要处理有符号的数字,因此在开始之前必须[有效地]对扩展进行签名。和/或右移是算术右移[符号位移位],而不是逻辑右移[零位移位] 对于乘法器/被乘数,ALU内部可能需要也可能不需要8位寄存器,但由于乘积寄存器必须为

有人能指出我做错了什么吗? 对于乘法器最右边的每一位,如果遇到一位,我会在乘积的左边添加被乘数。
谢谢你的帮助

据我所知,这似乎是一个“移位和加法”乘数

右移乘法器时,必须左移被乘数。旁注:实际ALU可能执行mux/demux,而不是实际移位,但原理相同

虽然输入reg是4位的,但由于您要处理有符号的数字,因此在开始之前必须[有效地]对扩展进行签名。和/或右移是算术右移[符号位移位],而不是逻辑右移[零位移位]

对于乘法器/被乘数,ALU内部可能需要也可能不需要8位寄存器,但由于乘积寄存器必须为8位,因此更容易直观地假设它们为8位

以下是此类乘数的顺序:

step    multiplier  multiplicand    product
        4           -6
1       00000100    11111010        00000000
2       00000010    11110100        00000000
3       00000001    11101000        11101000
4       00000000    11010000        11101000
5       00000000    10100000        11101000
6       00000000    01000000        11101000
7       00000000    10000000        11101000
8       00000000    00000000        11101000

step    multiplier  multiplicand    product
        -6          4
1       11111010    00000100        00000000
2       01111101    00001000        00001000
3       00111110    00010000        00001000
4       00011111    00100000        00101000
5       00001111    01000000        01101000
6       00000111    10000000        11101000
7       00000011    00000000        11101000
8       00000001    00000000        11101000

以下是我用来生成上述内容的演示程序:

#include <stdio.h>
#include <stdlib.h>

typedef unsigned int u32;

#define CMAX    8
int cidx;
char cache[CMAX][80];

char *
binof(u32 x)
{
    char *bf;

    bf = cache[cidx++];
    if (cidx >= CMAX)
        cidx = 0;

    for (int idx = 7;  idx >= 0;  --idx, x >>= 1)
        bf[idx] = (x & 1) ? '1' : '0';

    return bf;
}

void
dostep(int step,u32 x,u32 y,u32 p)
{
    printf("%d\t\t%s\t%s\t\t%s\n",step,binof(x),binof(y),binof(p));
}

void
dotest(int x,int y)
{
    u32 xu;
    u32 yu;
    u32 p;

    xu = x;
    xu &= 0xFF;

    yu = y;
    yu &= 0xFF;

    printf("step\tmultiplier\tmultiplicand\tproduct\n");
    printf("\t\t%d\t\t\t%d\n",x,y);

    p = 0;
    for (int step = 1;  step <= 8;  ++step) {
        if (xu & 1)
            p += yu;
        dostep(step,xu,yu,p);
        xu >>= 1;
        yu <<= 1;
    }
}

// main -- main program
int
main(int argc,char **argv)
{
    char *cp;

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        cp = *argv;
        if (*cp != '-')
            break;

        switch (cp[1]) {
        default:
            break;
        }
    }

#if 0
    int x = atoi(argv[0]);
    int y = atoi(argv[1]);
#else
    int x = 4;
    int y = -6;
#endif
    dotest(x,y);
    printf("\n");
    dotest(y,x);

    return 0;
}

以下是更新的演示程序:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

typedef unsigned int u32;

#define OPUT \
    do { \
        fputc(chr,stdout); \
        olen += 1; \
    } while (0)

#define CMAX    8
int cidx;
char cache[CMAX][80];

int opt_swap;
int opt_early;

char *
binof(u32 x)
{
    char *bf;

    bf = cache[cidx++];
    if (cidx >= CMAX)
        cidx = 0;

    for (int idx = 7;  idx >= 0;  --idx, x >>= 1)
        bf[idx] = (x & 1) ? '1' : '0';

    return bf;
}

void __attribute__((__format__(__printf__,1,2)))
outf(const char *fmt,...)
{
    va_list ap;
    int chr;
    char *bp;
    int olen;
    char ibuf[100];

    va_start(ap,fmt);
    vsprintf(ibuf,fmt,ap);
    va_end(ap);

    olen = 0;
    bp = ibuf;

    for (chr = *bp++;  chr != 0;  chr = *bp++) {
        if (chr != '\t') {
            OPUT;
            continue;
        }

        chr = ' ';
        OPUT;

        while ((olen % 4) != 0)
            OPUT;
    }
}

void
dostep(int step,u32 x,u32 y,u32 p)
{
    outf("%d\t\t%s\t%s\t\t%s\n",step,binof(x),binof(y),binof(p));
}

void
dotest(int x,int y)
{
    u32 mplier;
    u32 mcand;
    int tmp;
    u32 p;

    mplier = x;
    mplier &= 0xFF;

    mcand = y;
    mcand &= 0xFF;

    if (opt_swap && ((mplier & 0x0F) > (mcand & 0x0F))) {
        p = mplier;
        mplier = mcand;
        mcand = p;

        tmp = x;
        x = y;
        y = tmp;
    }

    outf("\n");
    outf("step\tmultiplier\tmultiplicand\tproduct\n");
    outf("\t\t%d\t\t\t%d\n",x,y);

    p = 0;
    for (int step = 1;  step <= 8;  ++step) {
        if (opt_early) {
            if (mplier == 0)
                break;
            if (mcand == 0)
                break;
        }

        if (mplier & 1)
            p += mcand;
        dostep(step,mplier,mcand,p);

        mplier >>= 1;
        mcand <<= 1;
    }

    outf("\t\t\t\t\t\t\t\t\t%d\n",(char) p);
}

// main -- main program
int
main(int argc,char **argv)
{
    char *cp;
    int x;
    int y;
    int sep;
    const char *name;

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        cp = *argv;
        if (*cp != '-')
            break;

        switch (cp[1]) {
        default:
            break;
        }
    }

    switch (argc) {
    case 2:
        x = atoi(argv[0]);
        y = atoi(argv[1]);
        break;
    default:
        x = 4;
        y = -6;
        break;
    }

    sep = 0;
    for (opt_early = 0;  opt_early <= 1;  ++opt_early) {
        for (opt_swap = 0;  opt_swap <= 1;  ++opt_swap) {
            switch ((opt_early << 8) | (opt_swap << 0)) {
            case 0x0101:
                name = "early escape with autoswap";
                break;
            case 0x0100:
                name = "early escape";
                break;
            case 0x0001:
                name = "autoswap";
                break;
            default:
                name = "simple";
                break;
            }

            if (sep)
                outf("\n");
            sep = 1;

            for (int olen = 1;  olen <= 80;  ++olen)
                fputc('-',stdout);
            fputc('\n',stdout);

            outf("TYPE: %s\n",name);

            dotest(x,y);
            dotest(y,x);
        }
    }

    return 0;
}
#包括
#包括
#包括
typedef无符号整数u32;
#定义作品\
做{\
fputc(chr,stdout)\
olen+=1\
}而(0)
#定义CMAX 8
int-cidx;
字符缓存[CMAX][80];
国际期权互换;
尽早退出;
煤焦*
binof(u32 x)
{
char*bf;
bf=缓存[cidx++];
如果(cidx>=CMAX)
cidx=0;
对于(int idx=7;idx>=0;--idx,x>>=1)
bf[idx]=(x&1)?“1”:“0”;
返回高炉;
}
void uuu属性uuu((uuu格式uuu(uuu打印文件uuu,1,2)))
出口(常量字符*fmt,…)
{
va_列表ap;
int-chr;
char*bp;
内奥伦;
char-ibuf[100];
va_启动(ap、fmt);
vsprintf(ibuf、fmt、ap);
va_端(ap);
olen=0;
bp=ibuf;
for(chr=*bp++;chr!=0;chr=*bp++){
如果(chr!='\t'){
奥普特;
继续;
}
chr='';
奥普特;
而((olen%4)!=0)
奥普特;
}
}
无效的
dostep(整数步,u32 x,u32 y,u32 p)
{
OUT(“%d\t\t%s\t%s\t\t%s\n”,步骤,binof(x),binof(y),binof(p));
}
无效的
点测试(整数x,整数y)
{
u32放大器;
u32-mcand;
int tmp;
U32P;
mplier=x;
mplier&=0xFF;
mcand=y;
mcand&=0xFF;
if(opt_swap&((mplier&0x0F)>(mcand&0x0F))){
p=mplier;
mplier=mcand;
mcand=p;
tmp=x;
x=y;
y=tmp;
}
出口(“\n”);
输出(“步进\t乘法器\t乘法器\t产品\n”);
出口(“\t\t%d\t\t\t%d\n”,x,y);
p=0;
对于(int step=1;step>=1;

mcand据我所知,这似乎是一个“移位和加法”乘数

当您右移乘法器时,您必须左移被乘数。旁注:实际ALU可能执行mux/demux,而不是实际移位,但原理相同

当输入寄存器为4位时,由于您处理的是有符号数字,因此在开始之前必须[有效地]进行符号扩展。和/或当右移时,它是算术右移[符号位移位],而不是逻辑右移[零位移位]

对于乘法器/被乘数,ALU内部可能需要也可能不需要8位寄存器,但由于乘积寄存器必须为8位,因此更容易直观地假设它们为8位

以下是此类乘数的顺序:

step    multiplier  multiplicand    product
        4           -6
1       00000100    11111010        00000000
2       00000010    11110100        00000000
3       00000001    11101000        11101000
4       00000000    11010000        11101000
5       00000000    10100000        11101000
6       00000000    01000000        11101000
7       00000000    10000000        11101000
8       00000000    00000000        11101000

step    multiplier  multiplicand    product
        -6          4
1       11111010    00000100        00000000
2       01111101    00001000        00001000
3       00111110    00010000        00001000
4       00011111    00100000        00101000
5       00001111    01000000        01101000
6       00000111    10000000        11101000
7       00000011    00000000        11101000
8       00000001    00000000        11101000

以下是我用来生成上述内容的演示程序:

#include <stdio.h>
#include <stdlib.h>

typedef unsigned int u32;

#define CMAX    8
int cidx;
char cache[CMAX][80];

char *
binof(u32 x)
{
    char *bf;

    bf = cache[cidx++];
    if (cidx >= CMAX)
        cidx = 0;

    for (int idx = 7;  idx >= 0;  --idx, x >>= 1)
        bf[idx] = (x & 1) ? '1' : '0';

    return bf;
}

void
dostep(int step,u32 x,u32 y,u32 p)
{
    printf("%d\t\t%s\t%s\t\t%s\n",step,binof(x),binof(y),binof(p));
}

void
dotest(int x,int y)
{
    u32 xu;
    u32 yu;
    u32 p;

    xu = x;
    xu &= 0xFF;

    yu = y;
    yu &= 0xFF;

    printf("step\tmultiplier\tmultiplicand\tproduct\n");
    printf("\t\t%d\t\t\t%d\n",x,y);

    p = 0;
    for (int step = 1;  step <= 8;  ++step) {
        if (xu & 1)
            p += yu;
        dostep(step,xu,yu,p);
        xu >>= 1;
        yu <<= 1;
    }
}

// main -- main program
int
main(int argc,char **argv)
{
    char *cp;

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        cp = *argv;
        if (*cp != '-')
            break;

        switch (cp[1]) {
        default:
            break;
        }
    }

#if 0
    int x = atoi(argv[0]);
    int y = atoi(argv[1]);
#else
    int x = 4;
    int y = -6;
#endif
    dotest(x,y);
    printf("\n");
    dotest(y,x);

    return 0;
}

以下是更新的演示程序:

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

typedef unsigned int u32;

#define OPUT \
    do { \
        fputc(chr,stdout); \
        olen += 1; \
    } while (0)

#define CMAX    8
int cidx;
char cache[CMAX][80];

int opt_swap;
int opt_early;

char *
binof(u32 x)
{
    char *bf;

    bf = cache[cidx++];
    if (cidx >= CMAX)
        cidx = 0;

    for (int idx = 7;  idx >= 0;  --idx, x >>= 1)
        bf[idx] = (x & 1) ? '1' : '0';

    return bf;
}

void __attribute__((__format__(__printf__,1,2)))
outf(const char *fmt,...)
{
    va_list ap;
    int chr;
    char *bp;
    int olen;
    char ibuf[100];

    va_start(ap,fmt);
    vsprintf(ibuf,fmt,ap);
    va_end(ap);

    olen = 0;
    bp = ibuf;

    for (chr = *bp++;  chr != 0;  chr = *bp++) {
        if (chr != '\t') {
            OPUT;
            continue;
        }

        chr = ' ';
        OPUT;

        while ((olen % 4) != 0)
            OPUT;
    }
}

void
dostep(int step,u32 x,u32 y,u32 p)
{
    outf("%d\t\t%s\t%s\t\t%s\n",step,binof(x),binof(y),binof(p));
}

void
dotest(int x,int y)
{
    u32 mplier;
    u32 mcand;
    int tmp;
    u32 p;

    mplier = x;
    mplier &= 0xFF;

    mcand = y;
    mcand &= 0xFF;

    if (opt_swap && ((mplier & 0x0F) > (mcand & 0x0F))) {
        p = mplier;
        mplier = mcand;
        mcand = p;

        tmp = x;
        x = y;
        y = tmp;
    }

    outf("\n");
    outf("step\tmultiplier\tmultiplicand\tproduct\n");
    outf("\t\t%d\t\t\t%d\n",x,y);

    p = 0;
    for (int step = 1;  step <= 8;  ++step) {
        if (opt_early) {
            if (mplier == 0)
                break;
            if (mcand == 0)
                break;
        }

        if (mplier & 1)
            p += mcand;
        dostep(step,mplier,mcand,p);

        mplier >>= 1;
        mcand <<= 1;
    }

    outf("\t\t\t\t\t\t\t\t\t%d\n",(char) p);
}

// main -- main program
int
main(int argc,char **argv)
{
    char *cp;
    int x;
    int y;
    int sep;
    const char *name;

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        cp = *argv;
        if (*cp != '-')
            break;

        switch (cp[1]) {
        default:
            break;
        }
    }

    switch (argc) {
    case 2:
        x = atoi(argv[0]);
        y = atoi(argv[1]);
        break;
    default:
        x = 4;
        y = -6;
        break;
    }

    sep = 0;
    for (opt_early = 0;  opt_early <= 1;  ++opt_early) {
        for (opt_swap = 0;  opt_swap <= 1;  ++opt_swap) {
            switch ((opt_early << 8) | (opt_swap << 0)) {
            case 0x0101:
                name = "early escape with autoswap";
                break;
            case 0x0100:
                name = "early escape";
                break;
            case 0x0001:
                name = "autoswap";
                break;
            default:
                name = "simple";
                break;
            }

            if (sep)
                outf("\n");
            sep = 1;

            for (int olen = 1;  olen <= 80;  ++olen)
                fputc('-',stdout);
            fputc('\n',stdout);

            outf("TYPE: %s\n",name);

            dotest(x,y);
            dotest(y,x);
        }
    }

    return 0;
}
#包括
#包括
#包括
typedef无符号整数u32;
#定义作品\
做{\
fputc(chr,stdout)\
olen+=1\
}而(0)
#定义CMAX 8
int-cidx;
字符缓存[CMAX][80];
国际期权互换;
尽早退出;
煤焦*
binof(u32 x)
{
char*bf;
bf=缓存[cidx++];
如果(cidx>=CMAX)
cidx=0;
对于(int idx=7;idx>=0;--idx,x>>=1)
bf[idx]=(x&1)?“1”:“0”;
返回高炉;
}
void uuu属性uuu((uuu格式uuu(uuu打印文件uuu,1,2)))
出口(常量字符*fmt,…)
{
va_列表ap;
int-chr;
char*bp;
内奥伦;
char-ibuf[100];
va_启动(ap、fmt);
vsprintf(ibuf、fmt、ap);
va_端(ap);
olen=0;
bp=ibuf;
for(chr=*bp++;chr!=0;chr=*bp++){
如果(chr!='\t'){
奥普特;
继续;
}
chr='';
奥普特;
而((olen%4)!=0)
奥普特;
}
}
无效的
dostep(整数步,u32 x,u32 y,u32 p)
{
OUT(“%d\t\t%s\t%s\t\t%s\n”,步骤,binof(x),binof(y),binof(p));
}
无效的
点测试(整数x,整数y)
{
u32放大器;
u32-mcand;
int tmp;
U32P;
mplier=x;
mplier&=0xFF;
mcand=y;
mcand&=0xFF;
if(opt_swap&((mplier&0x0F)>(mcand&0x0F))){
p=mplier;
mplier=mcand;
mcand=p;
tmp=x;
x=y;
y=tmp;
}
出口(“\n”);
输出(“步进\t乘法器\t乘法器\t产品\n”);
出口(“\t\t%d\t\t\t%d\n”,x,y);
p=0;
对于(int step=1;step>=1;

MCA和您的乘法器使用的是较旧的算法,它处理乘法的速度要慢得多。是的,毫无疑问。移位和加法是基本的,但速度很慢。“实”乘法器将在一两个周期内使用更多的电路来完成此操作。图中没有足够的信息[例如,控制测试块做什么,反馈路径中有什么,或ALU块中的组合逻辑等]。根据您所研究的模型(例如华莱士树等),此信息是隐含的所以,根据我所看到的和你在表中看到的,我不得不猜测。你使用的是较旧的算法,它处理乘法的速度要慢得多。是的,毫无疑问。移位和加法是基本的,但速度很慢。一个“实”乘法器会在一两个周期内使用更多的电路。图表中没有足够的信息[例如,控制测试块做什么,反馈路径中有什么,或ALU块中的组合逻辑等]。根据您所使用的模型,此信息是隐含的