目的:因為FPGA版的容量不夠大,無法把4G的ROM與SRAM全部燒進去,必須將所使用的到容量縮到最小。
下圖為MIPS記憶體的配置方式,PCspim也是依照此放式來配置記憶體。
在撰寫MIPS R3000時,我們將程式碼區段放置在ROM內,且將PC從0x0000 0000開始執行。推疊跟靜態資料放置在SRAM內。
我們以移位的程式來做範例
經過lcc compiler與PCspim模擬後,可知道
R29 (sp) = 7fffeffc $sp 7fffeffc
DATA 靜態資料0x10000000 到 0x10040000
[0x10000000]...[0x10010000] 0x00000000
[0x10010000] 0x0000007e 0x0000007b 0x0000007c 0x00000076
[0x10010010] 0x0000007c 0x00000075 0x00000077 0x00000074
[0x10010020] 0x00000078 0x0000007a 0x00000077 0x00000078
[0x10010030] 0x00000076 0x00000079 0x00000077 0x00000078
[0x10010040] 0x00000081 0x00000079 0x0000007e 0x00000077
. .
. .
[0x100100d0] 0x00000096 0x00000096 0x00000096 0x00000098
[0x100100e0] 0x0000009f 0x000000a0 0x0000009e 0x0000009b
[0x100100f0] 0x0000009b 0x0000009b 0x0000009b 0x0000009a
[0x10010100]...[0x10040000] 0x00000000
STACK
[0x7fffeffc] 0x00000000
為了縮減ROM與SRAM的容量,我們將$pc=0x0000 0000 根據組合語言我們可以知道靜態資料會用到的記憶體位址由0x1001 0000 到 0x1001 00ff,固靜態資料必須大於0x1001 00ff,在根據組合語言內對$sp所做的運算,我們將靜態資料設成0x1001 0110
[0x00400024] 0x27bdfef0 addiu $29, $29, -272 ; 79: addu $sp,$sp,-272
為了避免堆疊與靜態資料衝到,所以$sp=0x1001 0110 + 272 ==> 0x1001 0220
下圖為修改過後的記憶體配置方式:
因為0x1001 0220 ==> 268501536 要宣告的陣列過大,所以我們將SRAM的address全部往前位移,位移過後的記憶體配置方式如下圖:
2007年12月10日 星期一
2007年12月8日 星期六
1208 輸出腳位設定
目的:
C語言轉換成MIPS R3000組合語言轉換成機器碼後放置在MIPS R3000內,如何檢查C語言執行結果與MIPS R3000的輸出結果相符合便成一個重要的問題
流程圖:
C語言轉換成MIPS R3000組合語言轉換成機器碼後放置在MIPS R3000內,如何檢查C語言執行結果與MIPS R3000的輸出結果相符合便成一個重要的問題
流程圖:
C語言:
#include
main(){
int aa=111,i,j,f[8][8]=
{{126,123,124,118,124,117,119,116},
#include
main(){
int aa=111,i,j,f[8][8]=
{{126,123,124,118,124,117,119,116},
{120,122,119,120,118,121,119,120},
{129,121,126,119,124,118,123,117},
{121,127,120,123,122,122,118,121},
{130,130,125,126,127,131,127,124},
{140,139,140,146,144,139,140,140},
{151,147,147,150,150,150,150,152},
{159,160,158,155,155,155,155,154}};
{121,127,120,123,122,122,118,121},
{130,130,125,126,127,131,127,124},
{140,139,140,146,144,139,140,140},
{151,147,147,150,150,150,150,152},
{159,160,158,155,155,155,155,154}};
for ( i=0;i<8;i++){
for( j=0;j<8;j++){
f[i][j]=f[i][j]-128;
aa=f[i][j]-128;
}}}
for( j=0;j<8;j++){
f[i][j]=f[i][j]-128;
aa=f[i][j]-128;
}}}
程式的目的主要是將f[8][8]的各個元素減128,宣告一個數aa目的是要將所有運算過後的元素放置在aa裡面,使得在PCSpim裡面可以較容易找出運算過後的各個元素放置在記憶體的哪個部份。
經過LCC compiler 與自動轉換程式修改部分組合語言後,使用PCspim找出aa所存放的記憶體位址,並且檢查答案是否正確。
aa=111
0x3416006f ori $22, $0, 111 ; 84: la $22,111
aa=f[i][j]-128;
0x8f180000 lw $24, 0($24) ; 114: lw $24,($24)
0x2716ff80 addiu $22, $24, -128 ; 115: subu $22,$24,128
利用C語言與組合語言對照,可發現aa所存放的位置在$22內,所以我們只要將$22傳給輸出腳位,就可以很容易的在synapitCAD模擬出來的波形圖內,觀察出答案是否與C語言執行出來的結果相符合。
IO0=regs[22];
assign IO0=regs[22];
經過LCC compiler 與自動轉換程式修改部分組合語言後,使用PCspim找出aa所存放的記憶體位址,並且檢查答案是否正確。
aa=111
0x3416006f ori $22, $0, 111 ; 84: la $22,111
aa=f[i][j]-128;
0x8f180000 lw $24, 0($24) ; 114: lw $24,($24)
0x2716ff80 addiu $22, $24, -128 ; 115: subu $22,$24,128
利用C語言與組合語言對照,可發現aa所存放的位置在$22內,所以我們只要將$22傳給輸出腳位,就可以很容易的在synapitCAD模擬出來的波形圖內,觀察出答案是否與C語言執行出來的結果相符合。
IO0=regs[22];
assign IO0=regs[22];
下圖為C語言執行結果與synapitCAD執行結果對照:
2007年10月25日 星期四
2007/1025 如何放置機器碼到ROM內
從PCSpim中抓取機器碼
基本上,以下的指令可以從ROM[0]開始放置
但是我們可以從指令中看到0x0c100009 jal 0x00400024 [main]
這個指令是跳躍到主程式所在ROM內執行
所以必須將主程式以後的指令放置到他所要跳躍的ROM內
從0x0c100009 jal 0x00400024 [main] 中解碼
0c100009 ==> 0000 1100 0001 0000 0000 0000 0000 1001
需要跳躍到100009轉成十進制1048585,必須將主程式放置在ROM[1048585]以後
部份程式碼如下
while(!feof(fi))
{
cf=fgetc(fi);
if (cf!='\n') i=i+1;
if ((cf=='\n')&&(k<=39)) {k=4*j-1; j=j+1;continue;} //0~35
if (k==39){
k=1048588;
j=262148; }
if ((cf=='\n')&&(k>39)) {k=4*j; j=j+1;continue;} //1048588~
if ((i%8)==1) {
printf("rom[%2d]= ",k);fprintf(fo,"rom[%d]=",k);k=k-1;}
if ( (i%8)==0 ) {
fprintf(fo,"%c;\n",cf);printf("%c;\n",cf);}
else {fprintf(fo,"%c",cf);printf("%c",cf);}
}
經過擷取與轉換後最後結果
rom[3]=10001111;
rom[2]=10100100;
rom[1]=00000000;
rom[0]=00000000;
rom[7]=00100111;
rom[6]=10100101;
rom[5]=00000000;
rom[4]=00000100;
rom[11]=00100100;
rom[10]=10100110;
rom[9]=00000000;
rom[8]=00000100;
rom[15]=00000000;
rom[14]=00000100;
rom[13]=00010000;
rom[12]=10000000;
rom[19]=00000000;
rom[18]=11000010;
rom[17]=00110000;
rom[16]=00100001;
rom[23]=00001100;
rom[22]=00010000;
rom[21]=00000000;
rom[20]=00001001;
rom[27]=00000000;
rom[26]=00000000;
rom[25]=00000000;
rom[24]=00000000;
rom[31]=00110100;
rom[30]=00000010;
rom[29]=00000000;
rom[28]=00001010;
rom[35]=00000000;
rom[34]=00000000;
rom[33]=00000000;
rom[32]=00001100;
rom[1048588]=00100111;
rom[1048587]=10111101;
rom[1048586]=11111111;
rom[1048585]=11100000;
rom[1048592]=11110111;
rom[1048591]=10111100;
rom[1048590]=00000000;
rom[1048589]=00000000;
rom[1048596]=11110111;
rom[1048595]=10111110;
rom[1048594]=00000000;
rom[1048593]=00001000;
rom[1048600]=00111100;
rom[1048599]=00000001;
rom[1048598]=00010000;
rom[1048597]=00000001;
rom[1048604]=11000100;
rom[1048603]=00111110;
rom[1048602]=00000000;
rom[1048601]=00000100;
rom[1048608]=00111100;
rom[1048607]=00000001;
rom[1048606]=00010000;
rom[1048605]=00000001;
rom[1048612]=11000100;
rom[1048611]=00111100;
rom[1048610]=00000000;
rom[1048609]=00000000;
rom[1048616]=01000110;
rom[1048615]=00011100;
rom[1048614]=11110100;
rom[1048613]=10000000;
rom[1048620]=11100111;
rom[1048619]=10110010;
rom[1048618]=00000000;
rom[1048617]=00011100;
rom[1048624]=01000110;
rom[1048623]=00011110;
rom[1048622]=11100100;
rom[1048621]=10000001;
rom[1048628]=11100111;
rom[1048627]=10110010;
rom[1048626]=00000000;
rom[1048625]=00011000;
rom[1048632]=00000000;
rom[1048631]=00000000;
rom[1048630]=00010000;
rom[1048629]=00100001;
rom[1048636]=11010111;
rom[1048635]=10111100;
rom[1048634]=00000000;
rom[1048633]=00000000;
rom[1048640]=11010111;
rom[1048639]=10111110;
rom[1048638]=00000000;
rom[1048637]=00001000;
rom[1048644]=00100111;
rom[1048643]=10111101;
rom[1048642]=00000000;
rom[1048641]=00100000;
rom[1048648]=00000011;
rom[1048647]=11100000;
rom[1048646]=00000000;
rom[1048645]=00001000;
基本上,以下的指令可以從ROM[0]開始放置
但是我們可以從指令中看到0x0c100009 jal 0x00400024 [main]
這個指令是跳躍到主程式所在ROM內執行
所以必須將主程式以後的指令放置到他所要跳躍的ROM內
從0x0c100009 jal 0x00400024 [main] 中解碼
0c100009 ==> 0000 1100 0001 0000 0000 0000 0000 1001
需要跳躍到100009轉成十進制1048585,必須將主程式放置在ROM[1048585]以後
部份程式碼如下
while(!feof(fi))
{
cf=fgetc(fi);
if (cf!='\n') i=i+1;
if ((cf=='\n')&&(k<=39)) {k=4*j-1; j=j+1;continue;} //0~35
if (k==39){
k=1048588;
j=262148; }
if ((cf=='\n')&&(k>39)) {k=4*j; j=j+1;continue;} //1048588~
if ((i%8)==1) {
printf("rom[%2d]= ",k);fprintf(fo,"rom[%d]=",k);k=k-1;}
if ( (i%8)==0 ) {
fprintf(fo,"%c;\n",cf);printf("%c;\n",cf);}
else {fprintf(fo,"%c",cf);printf("%c",cf);}
}
經過擷取與轉換後最後結果
rom[3]=10001111;
rom[2]=10100100;
rom[1]=00000000;
rom[0]=00000000;
rom[7]=00100111;
rom[6]=10100101;
rom[5]=00000000;
rom[4]=00000100;
rom[11]=00100100;
rom[10]=10100110;
rom[9]=00000000;
rom[8]=00000100;
rom[15]=00000000;
rom[14]=00000100;
rom[13]=00010000;
rom[12]=10000000;
rom[19]=00000000;
rom[18]=11000010;
rom[17]=00110000;
rom[16]=00100001;
rom[23]=00001100;
rom[22]=00010000;
rom[21]=00000000;
rom[20]=00001001;
rom[27]=00000000;
rom[26]=00000000;
rom[25]=00000000;
rom[24]=00000000;
rom[31]=00110100;
rom[30]=00000010;
rom[29]=00000000;
rom[28]=00001010;
rom[35]=00000000;
rom[34]=00000000;
rom[33]=00000000;
rom[32]=00001100;
rom[1048588]=00100111;
rom[1048587]=10111101;
rom[1048586]=11111111;
rom[1048585]=11100000;
rom[1048592]=11110111;
rom[1048591]=10111100;
rom[1048590]=00000000;
rom[1048589]=00000000;
rom[1048596]=11110111;
rom[1048595]=10111110;
rom[1048594]=00000000;
rom[1048593]=00001000;
rom[1048600]=00111100;
rom[1048599]=00000001;
rom[1048598]=00010000;
rom[1048597]=00000001;
rom[1048604]=11000100;
rom[1048603]=00111110;
rom[1048602]=00000000;
rom[1048601]=00000100;
rom[1048608]=00111100;
rom[1048607]=00000001;
rom[1048606]=00010000;
rom[1048605]=00000001;
rom[1048612]=11000100;
rom[1048611]=00111100;
rom[1048610]=00000000;
rom[1048609]=00000000;
rom[1048616]=01000110;
rom[1048615]=00011100;
rom[1048614]=11110100;
rom[1048613]=10000000;
rom[1048620]=11100111;
rom[1048619]=10110010;
rom[1048618]=00000000;
rom[1048617]=00011100;
rom[1048624]=01000110;
rom[1048623]=00011110;
rom[1048622]=11100100;
rom[1048621]=10000001;
rom[1048628]=11100111;
rom[1048627]=10110010;
rom[1048626]=00000000;
rom[1048625]=00011000;
rom[1048632]=00000000;
rom[1048631]=00000000;
rom[1048630]=00010000;
rom[1048629]=00100001;
rom[1048636]=11010111;
rom[1048635]=10111100;
rom[1048634]=00000000;
rom[1048633]=00000000;
rom[1048640]=11010111;
rom[1048639]=10111110;
rom[1048638]=00000000;
rom[1048637]=00001000;
rom[1048644]=00100111;
rom[1048643]=10111101;
rom[1048642]=00000000;
rom[1048641]=00100000;
rom[1048648]=00000011;
rom[1048647]=11100000;
rom[1048646]=00000000;
rom[1048645]=00001000;
2007年10月24日 星期三
1024 C語言除法轉換組合語言注意事項
撰寫C語言必須注意除法的除數與被除數的宣告
Ex:
撰寫C語言除法,使用整數/浮點數,浮點數/整數,整數/整數
#includemain(){
int d=4,c=198;
float avg[4],ava[4],a=3.0;
avg[1]=c/3;
avg[2]=c/3.3;
ava[0]=198/a;
}
轉換後各個除法所轉換的組合語言
avg[1]=c/3; //編譯成div $30, $24
==>執行後結果正確
avg[2]=c/3.3; // c=198 編譯成 div.d $f18, $f18, $f16
==>執行後結果錯誤
ava[0]=198/a; // a=3.0 編譯成 div.s $f18, $f18, $f16
==>執行後結果正確
建議:將除法的被除數與除數皆設為浮點數形式。
Ex:
撰寫C語言除法,使用整數/浮點數,浮點數/整數,整數/整數
#include
int d=4,c=198;
float avg[4],ava[4],a=3.0;
avg[1]=c/3;
avg[2]=c/3.3;
ava[0]=198/a;
}
轉換後各個除法所轉換的組合語言
avg[1]=c/3; //編譯成div $30, $24
==>執行後結果正確
avg[2]=c/3.3; // c=198 編譯成 div.d $f18, $f18, $f16
==>執行後結果錯誤
ava[0]=198/a; // a=3.0 編譯成 div.s $f18, $f18, $f16
==>執行後結果正確
建議:將除法的被除數與除數皆設為浮點數形式。
2007年10月13日 星期六
1013 C語言轉換成MIPS R3000組合語言的機器碼流程
1.使用visua C++撰寫C語言,並確定正確性
2.使用lcc 編譯組合語言 lcc –Wf-target=mips/irix –S 檔案名稱.c
3.使用C語言修改組合語言
4.使用PCSpim測試正確性,並儲存資料成PCSpim.log
5.使用C語言擷取PCSpim.log內所需要的資料並轉換成verilog可用之格式
執行過程如下:
c語言
#include
main(){
float a=6.3,b=2.1,c=1.1,div;
div=a/b;
c=div/c;
//printf("%f %f",div,c);
}
執行結果:
使用lcc轉換並修改過後的程式碼如下:
lw $4, 0($29)
addiu $5, $29, 4
addiu $6, $5, 4
sll $2, $4, 2
addu $6, $6, $2
jal 0x00400024 [main]
nop
ori $2, $0, 10
syscall (exit)
addiu $29, $29, -64
sdc1 $f30, 0($29)
sw $30, 8($29)
addi $24, $29, 20
lui $8, 4097 [L.2]
addiu $8, $8, 40
addiu $10, $24, 40
lw $3, 0($8)
sw $3, 0($10)
addiu $8, $8, -8
addiu $10, $10, -8
lw $3, 0($8)
lw $9, 4($8)
sw $3, 0($10)
sw $9, 4($10)
sltu $1, $24, $10
bne $1, $0, -28 [L.9-0x00400064]
lui $1, 4097 [L.3]
lwc1 $f30, 44($1) [L.3]
ori $30, $0, 1
sll $24, $30, 2
addi $15, $29, 20
addu $15, $24, $15
addi $14, $29, 16
addu $24, $24, $14
lwc1 $f18, 0($24)
add.s $f18, $f18, $f30
swc1 $f18, 0($15)
addi $30, $30, 1
ori $24, $0, 10
slt $1, $24, $30
beq $1, $0, -44 [L.4-0x004000a0]
addu $2, $0, $0
ldc1 $f30, 0($29)
lw $30, 8($29)
addiu $29, $29, 64
jr $31 ; 56: j $31
擷取指令與部分資料如下(並未顯示全部)
轉換成二進制碼(只顯示資料部份)
轉換成verilog可只用的格式
2007年10月11日 星期四
2007/10/11 fedora安裝心得
錯誤原因:系統變慢,解壓縮或是開啟終端機要等上一兩分鐘...
發現錯誤:變慢或是沒有回應都是在網路現拔除的狀態下,懷疑為網路卡裝置出現問題
解決過程:將網路裝置停用,或是將網路線裝上即可回復,
發現錯誤:變慢或是沒有回應都是在網路現拔除的狀態下,懷疑為網路卡裝置出現問題
解決過程:將網路裝置停用,或是將網路線裝上即可回復,
訂閱:
文章 (Atom)