├── LICENSE
├── README.md
├── cache.c
├── cache.h
├── cache_data.c
├── cache_data.h
└── pipe.c
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # mips-cache-simulation
2 | 计算机系统原理mips五级流水线cache模拟 \
3 | cache.c:指令cache \
4 | cache_data.c:数据cache
5 |
本代码已被使用,请不要抄袭代码!!!
6 |
--------------------------------------------------------------------------------
/cache.c:
--------------------------------------------------------------------------------
1 |
2 | #include "cache.h"
3 | #include "pipe.h"
4 | #include "shell.h"
5 | #include "mips.h"
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #define MEM_DATA_START 0x10000000
12 | #define MEM_DATA_SIZE 0x00100000
13 | #define MEM_TEXT_START 0x00400000
14 | #define MEM_TEXT_SIZE 0x00100000
15 | #define MEM_STACK_START 0x7ff00000
16 | #define MEM_STACK_SIZE 0x00100000
17 | #define MEM_KDATA_START 0x90000000
18 | #define MEM_KDATA_SIZE 0x00100000
19 | #define MEM_KTEXT_START 0x80000000
20 | #define MEM_KTEXT_SIZE 0x00100000
21 | Cache cache;
22 |
23 | int waiting = 0;
24 |
25 | void init(){
26 | int i =0, j = 0;
27 | for(i=0;i<64;i++)
28 | {
29 | for(j=0;j<4;j++)
30 | {
31 | cache.cache_set[i].cache_line[j].valid = 0;
32 | cache.cache_set[i].cache_line[j].iru = 0;
33 | }
34 | }
35 | }
36 |
37 | void get_set(uint32_t address)
38 | {
39 | uint32_t tmp = address & 0xFFFFF;//取后20位
40 | uint32_t line = tmp >> 11 ;//取12-20位
41 | uint32_t set = (tmp >>5) &(0x6F);//取所对应的组号
42 | uint32_t begin = (address >> 5)<<5;
43 | printf("%d %d %d\n",tmp,line,set);
44 | }
45 | uint32_t cache_read(uint32_t address)
46 | {
47 | uint32_t tmp = address & 0xFFFFF;//取后20位
48 | uint32_t line = tmp >> 11 ;//取12-20位
49 | uint32_t set = (tmp >>5) &(0x3F);//取所对应的组号
50 | uint32_t inneraddress = address & 0x1f;
51 | // printf("inneraddress = %08x\n",inneraddress);
52 | uint32_t i = 0;
53 | // printf("ok_read\n");
54 | for(i=0;i<4;i++)
55 | {
56 | if(cache.cache_set[set].cache_line[i].valid==1)
57 | {
58 | if(cache.cache_set[set].cache_line[i].line == line)
59 | {
60 | uint32_t j = inneraddress;
61 | uint32_t word = (cache.cache_set[set].cache_line[i].data.mem[j]<<0) |
62 | (cache.cache_set[set].cache_line[i].data.mem[j+1]<<8)|
63 | (cache.cache_set[set].cache_line[i].data.mem[j+2]<<16) |
64 | (cache.cache_set[set].cache_line[i].data.mem[j+3]<<24);
65 | // printf("hit!");
66 | //system("pause");
67 | return word;
68 |
69 | }
70 |
71 | }
72 | }
73 | //printf("nohit!");
74 | waiting = 49;
75 | cache_write(address);
76 | return 0xffffffff;
77 | }
78 | void cache_write(uint32_t address)//写入一个块
79 | {
80 | // printf("oknow\n");
81 | uint32_t tmp = address & 0xFFFFF;//取后20位
82 | uint32_t line = tmp >> 11 ;//取12-20位
83 | uint32_t set = (tmp >>5) &(0x3F);//取所对应的组号
84 | uint32_t begin = (address >> 5);//块头
85 | // printf("set = %08x\n",set);
86 | begin = begin << 5;
87 | int i = 0;
88 | int tobeset = -1;
89 |
90 | for(i=0;i<4;i++)
91 | {
92 | if(cache.cache_set[set].cache_line[i].valid==0)
93 | {
94 | cache.cache_set[set].cache_line[i].valid = 1;
95 | cache.cache_set[set].cache_line[i].line = line;//对应第几个群
96 | // printf("%d %d\n",set,i);
97 | tobeset = i;//要写的列
98 | cache.cache_set[set].cache_line[i].iru = 0;
99 | break;
100 | }
101 | }
102 | for(i=0;i<4;i++)
103 | {
104 | if(tobeset==i)continue;
105 | else
106 | {
107 | if(cache.cache_set[set].cache_line[i].iru<3)
108 | cache.cache_set[set].cache_line[i].iru++;
109 | }
110 | }
111 | if(tobeset==-1){
112 | uint8_t maxn = 0;
113 | int i;
114 | for(i=0;i<4;i++)
115 | {
116 | if(cache.cache_set[set].cache_line[i].iru==0)continue;
117 | else
118 | {
119 | if(cache.cache_set[set].cache_line[i].iru<3)
120 | cache.cache_set[set].cache_line[i].iru++;
121 | if(maxn<=cache.cache_set[set].cache_line[i].iru)
122 | {
123 | maxn = cache.cache_set[set].cache_line[i].iru;
124 | tobeset = i;
125 | }
126 | }
127 | }
128 | // if(tobeset < 0 || tobeset > 3) {
129 | // printf("%d\n",tobeset);
130 | // printf("fuck you re!");
131 | // exit(1);
132 | // }
133 | cache.cache_set[set].cache_line[tobeset].valid = 1;
134 | cache.cache_set[set].cache_line[tobeset].line = line;//对应第几个群
135 | cache.cache_set[set].cache_line[tobeset].iru = 0;
136 | // return;//待修改
137 | }
138 |
139 | // printf("%08x",begin);
140 | for(i = 0;i<8;i++)//读取32个字节作为一块
141 | {
142 | uint32_t word = mem_read_32(begin);
143 | cache.cache_set[set].cache_line[tobeset].data.mem[i*4] = (uint8_t)(word>>0)&0xff;
144 | cache.cache_set[set].cache_line[tobeset].data.mem[i*4+1] = (uint8_t)(word>>8)&0xff;
145 | cache.cache_set[set].cache_line[tobeset].data.mem[i*4+2] = (uint8_t)(word>>16)&0xff;
146 | cache.cache_set[set].cache_line[tobeset].data.mem[i*4+3] = (uint8_t)(word>>24)&0xff;
147 | begin+=4;
148 | }
149 |
150 | }
--------------------------------------------------------------------------------
/cache.h:
--------------------------------------------------------------------------------
1 | #ifndef CACHE
2 | #define CACHE
3 |
4 | #include "stdio.h"
5 | #include "mips.h"
6 | #include "stdbool.h"
7 | #include "stdint.h"
8 | typedef struct //数据区,相当于一个块
9 | {
10 | uint8_t mem[32];//一个块有32byte
11 | }Data;
12 |
13 | typedef struct //每行cache
14 | {
15 | bool valid;//是否可用
16 | uint8_t iru;//iru位,因为4way,所以取后两位即可
17 | uint16_t line;//9位行号
18 | Data data;//数据区
19 | }Cache_line;
20 |
21 | typedef struct //每组cache
22 | {
23 | Cache_line cache_line[4];//一组有四行
24 | }Cache_set;
25 | typedef struct
26 | {
27 | Cache_set cache_set[64];//一共有64组
28 | }Cache;
29 | extern Cache cache;
30 | void init();
31 | void get_set(uint32_t address);
32 | void cache_write(uint32_t address);//写入一个块
33 | uint32_t cache_read(uint32_t address);//从给定本应读取的内存地址中读取数据
34 | void cache_replace(Cache_line cache_line);//给定行,进行替换
35 |
36 | extern int waiting;
37 |
38 | #endif
--------------------------------------------------------------------------------
/cache_data.c:
--------------------------------------------------------------------------------
1 |
2 | #include "cache_data.h"
3 | #include "pipe.h"
4 | #include "shell.h"
5 | #include "mips.h"
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | #define MEM_DATA_START 0x10000000
12 | #define MEM_DATA_SIZE 0x00100000
13 | #define MEM_TEXT_START 0x00400000
14 | #define MEM_TEXT_SIZE 0x00100000
15 | #define MEM_STACK_START 0x7ff00000
16 | #define MEM_STACK_SIZE 0x00100000
17 | #define MEM_KDATA_START 0x90000000
18 | #define MEM_KDATA_SIZE 0x00100000
19 | #define MEM_KTEXT_START 0x80000000
20 | #define MEM_KTEXT_SIZE 0x00100000
21 | Cache_data cache_data;
22 | int waiting_data = 0;
23 | void data_init(){
24 | int i =0, j = 0;
25 | for(i=0;i<256;i++)
26 | {
27 | for(j=0;j<8;j++)
28 | {
29 | cache_data.cache_data_set[i].cache_data_line[j].valid = 0;
30 | cache_data.cache_data_set[i].cache_data_line[j].iru = 0;
31 | cache_data.cache_data_set[i].cache_data_line[j].dirty = 0;
32 | }
33 | }
34 | }
35 | uint32_t cache_data_read(uint32_t address)
36 | {
37 | // printf("read address = 0x%08x\n",address);
38 | uint32_t line = address >> 13 ;//取前19位
39 | uint32_t set = (address >>5) &(0xFF);//取所对应的组号
40 | uint32_t inneraddress = address & 0x1f;
41 | uint32_t i = 0;
42 | // printf("line = %d set = %d inneraddress = %d\n",line,set,inneraddress);
43 | for(i=0;i<8;i++)
44 | {
45 | if(cache_data.cache_data_set[set].cache_data_line[i].valid==1)//当前位有效的时候
46 | {
47 | if(cache_data.cache_data_set[set].cache_data_line[i].line == line)//当前行号和对应的主存行号相同
48 | {
49 | uint32_t j = inneraddress;//内部地址
50 | uint32_t word = (cache_data.cache_data_set[set].cache_data_line[i].data.mem[j]<<0) |
51 | (cache_data.cache_data_set[set].cache_data_line[i].data.mem[j+1]<<8) |
52 | (cache_data.cache_data_set[set].cache_data_line[i].data.mem[j+2]<<16) |
53 | (cache_data.cache_data_set[set].cache_data_line[i].data.mem[j+3]<<24);
54 | return word;
55 |
56 | }
57 |
58 | }
59 | }
60 | waiting_data = 49;
61 | cache_data_load(address);
62 | return 0xffffffff;
63 | }
64 | void cache_data_load(uint32_t address)//给定地址,要求把地址所在的块中读出一个块存到cache里
65 | {
66 | //内存地址 = 行号19位 + 组号8位 + 块内地址5位
67 |
68 | uint32_t line = address >> 13 ;//取前19位,要写入的line
69 | uint32_t set = (address >>5) &(0xFF);//取所对应的组号
70 | uint32_t begin = (address >> 5);//块头
71 | begin = begin << 5;
72 | int i = 0;
73 | int tobeset = -1;//需要被替换的way
74 | uint32_t getline = 0;
75 | uint32_t getset = 0;
76 | for(i=0;i<8;i++)
77 | {
78 | if(cache_data.cache_data_set[set].cache_data_line[i].valid==0)
79 | {
80 | cache_data.cache_data_set[set].cache_data_line[i].valid = 1;
81 | cache_data.cache_data_set[set].cache_data_line[i].line = line;//对应第几个群
82 |
83 | tobeset = i;//要写的列
84 |
85 | cache_data.cache_data_set[set].cache_data_line[i].iru = 0;
86 | break;
87 | }
88 | }
89 |
90 |
91 | for(i=0;i<8;i++)
92 | {
93 | if(tobeset==i)continue;
94 | else
95 | {
96 | if(cache_data.cache_data_set[set].cache_data_line[i].iru<7)
97 | cache_data.cache_data_set[set].cache_data_line[i].iru++;
98 | }
99 | }
100 | if(tobeset==-1){
101 | uint8_t maxn = 0;
102 | int i;
103 | for(i=0;i<8;i++)
104 | {
105 | if(cache_data.cache_data_set[set].cache_data_line[i].iru==0)continue;
106 | else
107 | {
108 | if(cache_data.cache_data_set[set].cache_data_line[i].iru<7)
109 | cache_data.cache_data_set[set].cache_data_line[i].iru++;
110 | if(maxn<=cache_data.cache_data_set[set].cache_data_line[i].iru)
111 | {
112 | maxn = cache_data.cache_data_set[set].cache_data_line[i].iru;
113 | tobeset = i;//将要替换的行
114 | getline = cache_data.cache_data_set[set].cache_data_line[i].line;//将要替换的行的行号
115 | getset = set;
116 | }
117 | }
118 | }
119 |
120 | //准备写回主存
121 | if(cache_data.cache_data_set[set].cache_data_line[tobeset].dirty == 0)goto ok;//不脏的时候无需写回主存
122 | uint32_t readdress = 0;
123 | readdress = (getline<<13)|(set<<5);//将要替换的行的源地址块头
124 | for(i=0;i<8;i++)//一个块是32 byte 要读八次
125 | {
126 | uint32_t word = cache_data_read(readdress);//根据主存地址从cache中读出一个字
127 | mem_write_32(readdress,word);//将这一个字写回到主存
128 | readdress+=4;
129 | }
130 | ok:;
131 | cache_data.cache_data_set[set].cache_data_line[tobeset].valid = 1;
132 | cache_data.cache_data_set[set].cache_data_line[tobeset].line = line;//对应第几个群
133 | cache_data.cache_data_set[set].cache_data_line[tobeset].iru = 0;
134 | }
135 |
136 | for(i = 0;i<8;i++)//读取32个字节作为一块
137 | {
138 | uint32_t word = mem_read_32(begin);
139 | cache_data.cache_data_set[set].cache_data_line[tobeset].data.mem[i*4] = (uint8_t)(word>>0)&0xff;
140 | cache_data.cache_data_set[set].cache_data_line[tobeset].data.mem[i*4+1] = (uint8_t)(word>>8)&0xff;
141 | cache_data.cache_data_set[set].cache_data_line[tobeset].data.mem[i*4+2] = (uint8_t)(word>>16)&0xff;
142 | cache_data.cache_data_set[set].cache_data_line[tobeset].data.mem[i*4+3] = (uint8_t)(word>>24)&0xff;
143 | begin+=4;
144 | }
145 | }
146 |
147 |
148 | void cache_data_write_val(uint32_t address,uint32_t write)//把本应写在主存address里的write写到cache里
149 | {
150 | if(cache_data_read(address)==0xffffffff){
151 | cache_data_load(address);
152 | }
153 | uint32_t line = address >> 13 ;//取前19位
154 | uint32_t set = (address >>5) &(0xFF);//取所对应的组号
155 | uint32_t inneraddress = address & 0x1f;
156 | uint32_t i = 0;
157 |
158 | for(i=0;i<8;i++)
159 | {
160 | if(cache_data.cache_data_set[set].cache_data_line[i].valid==1)//当前位有效的时候
161 | {
162 | if(cache_data.cache_data_set[set].cache_data_line[i].line == line)//当前行号和对应的主存行号相同
163 | {
164 | uint32_t j = inneraddress;//内部地址
165 | cache_data.cache_data_set[set].cache_data_line[i].dirty = 1;
166 | cache_data.cache_data_set[set].cache_data_line[i].data.mem[j] = (uint8_t)(write>>0)&0xff;
167 | cache_data.cache_data_set[set].cache_data_line[i].data.mem[j+1] = (uint8_t)(write>>8)&0xff;
168 | cache_data.cache_data_set[set].cache_data_line[i].data.mem[j+2] = (uint8_t)(write>>16)&0xff;
169 | cache_data.cache_data_set[set].cache_data_line[i].data.mem[j+3] = (uint8_t)(write>>24)&0xff;
170 | return;
171 | }
172 | }
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/cache_data.h:
--------------------------------------------------------------------------------
1 | #ifndef CACHEDATA
2 | #define CACHEDATA
3 |
4 | #include "stdio.h"
5 | #include "mips.h"
6 | #include "stdbool.h"
7 | #include "stdint.h"
8 | typedef struct //数据区,相当于一个块
9 | {
10 | uint8_t mem[32];//一个块有32byte
11 | }Data_1;
12 | typedef struct //每行cache
13 | {
14 | bool valid;//是否可用
15 | bool dirty;
16 | uint8_t iru;//lru位,因为8way,所以取后三位即可
17 | uint32_t line;//19位行号
18 | Data_1 data;//数据区
19 | }Cache_data_line;
20 | typedef struct //每组cache
21 | {
22 | Cache_data_line cache_data_line[8];//一组有八行
23 | }Cache_data_set;
24 | typedef struct
25 | {
26 | Cache_data_set cache_data_set[256];//一共有256组
27 | }Cache_data;
28 | extern Cache_data cache_data;
29 | void data_init();
30 | void cache_data_write_val(uint32_t address,uint32_t write);//写入一个块
31 | void cache_data_load(uint32_t address);//写入一个块
32 | uint32_t cache_data_read(uint32_t address);//从给定本应读取的内存地址中读取数据
33 | extern int waiting_data;
34 | #endif
35 |
36 |
--------------------------------------------------------------------------------
/pipe.c:
--------------------------------------------------------------------------------
1 | #include "pipe.h"
2 | #include "shell.h"
3 | #include "mips.h"
4 | #include "cache.h"
5 | #include "cache_data.h"
6 | #include
7 | #include
8 | #include
9 | #include
10 |
11 | //#define DEBUG
12 |
13 | /* debug */
14 | void print_op(Pipe_Op *op)
15 | {
16 | if (op)
17 | printf("OP (PC=%08x inst=%08x) src1=R%d (%08x) src2=R%d (%08x) dst=R%d valid %d (%08x) br=%d taken=%d dest=%08x mem=%d addr=%08x\n",
18 | op->pc, op->instruction, op->reg_src1, op->reg_src1_value, op->reg_src2, op->reg_src2_value, op->reg_dst, op->reg_dst_value_ready,
19 | op->reg_dst_value, op->is_branch, op->branch_taken, op->branch_dest, op->is_mem, op->mem_addr);
20 | else
21 | printf("(null)\n");
22 | }
23 |
24 | /* global pipeline state */
25 | Pipe_State pipe;
26 |
27 | void pipe_init()
28 | {
29 | init();
30 | data_init();
31 | memset(&pipe, 0, sizeof(Pipe_State));
32 | pipe.PC = 0x00400000;
33 | }
34 |
35 | void pipe_cycle()
36 | {
37 | #ifdef DEBUG
38 | printf("\n\n----\n\nPIPELINE:\n");
39 | printf("DCODE: "); print_op(pipe.decode_op);
40 | printf("EXEC : "); print_op(pipe.execute_op);
41 | printf("MEM : "); print_op(pipe.mem_op);
42 | printf("WB : "); print_op(pipe.wb_op);
43 | printf("\n");
44 | #endif
45 |
46 | pipe_stage_wb();
47 | pipe_stage_mem();
48 | pipe_stage_execute();
49 | pipe_stage_decode();
50 | pipe_stage_fetch();
51 |
52 | /* handle branch recoveries */
53 | if (pipe.branch_recover) {
54 | #ifdef DEBUG
55 | printf("branch recovery: new dest %08x flush %d stages\n", pipe.branch_dest, pipe.branch_flush);
56 | #endif
57 |
58 | pipe.PC = pipe.branch_dest;
59 |
60 | if (pipe.branch_flush >= 2) {
61 | if (pipe.decode_op) free(pipe.decode_op);
62 | pipe.decode_op = NULL;
63 | }
64 |
65 | if (pipe.branch_flush >= 3) {
66 | if (pipe.execute_op) free(pipe.execute_op);
67 | pipe.execute_op = NULL;
68 | }
69 |
70 | if (pipe.branch_flush >= 4) {
71 | if (pipe.mem_op) free(pipe.mem_op);
72 | pipe.mem_op = NULL;
73 | }
74 |
75 | if (pipe.branch_flush >= 5) {
76 | if (pipe.wb_op) free(pipe.wb_op);
77 | pipe.wb_op = NULL;
78 | }
79 |
80 | pipe.branch_recover = 0;
81 | pipe.branch_dest = 0;
82 | pipe.branch_flush = 0;
83 |
84 | stat_squash++;
85 | }//printf("after\n");
86 | }
87 |
88 | void pipe_recover(int flush, uint32_t dest)
89 | {
90 | /* if there is already a recovery scheduled, it must have come from a later
91 | * stage (which executes older instructions), hence that recovery overrides
92 | * our recovery. Simply return in this case. */
93 | if (pipe.branch_recover) return;
94 |
95 | /* schedule the recovery. This will be done once all pipeline stages simulate the current cycle. */
96 | pipe.branch_recover = 1;
97 | pipe.branch_flush = flush;
98 | pipe.branch_dest = dest;
99 | }
100 |
101 | void pipe_stage_wb()
102 | {
103 | /* if there is no instruction in this pipeline stage, we are done */
104 | if (!pipe.wb_op)
105 | return;
106 |
107 | /* grab the op out of our input slot */
108 | Pipe_Op *op = pipe.wb_op;
109 | pipe.wb_op = NULL;
110 |
111 | /* if this instruction writes a register, do so now */
112 | if (op->reg_dst != -1 && op->reg_dst != 0) {
113 | pipe.REGS[op->reg_dst] = op->reg_dst_value;
114 | #ifdef DEBUG
115 | printf("R%d = %08x\n", op->reg_dst, op->reg_dst_value);
116 | #endif
117 | }
118 | /* if this was a syscall, perform action */
119 | if (op->opcode == OP_SPECIAL && op->subop == SUBOP_SYSCALL) {
120 | if (op->reg_src1_value == 0xA) {
121 | pipe.PC = op->pc; /* fetch will do pc += 4, then we stop with correct PC */
122 | RUN_BIT = 0;
123 | }
124 | }
125 |
126 | /* free the op */
127 | free(op);
128 |
129 | stat_inst_retire++;
130 | }
131 |
132 | void pipe_stage_mem()
133 | {
134 | // printf("mem\n");
135 | /* if there is no instruction in this pipeline stage, we are done */
136 | if (!pipe.mem_op)
137 | return;
138 |
139 | /* grab the op out of our input slot */
140 | Pipe_Op *op = pipe.mem_op;
141 | uint32_t val = 0;
142 | if (op->is_mem){
143 | uint32_t word = 0;
144 | if (waiting_data == 0) {
145 | word = cache_data_read(op->mem_addr & ~3);
146 | }
147 | if(waiting_data == 0)
148 | {
149 | if(word == 0xffffffff)
150 | {
151 | val = cache_data_read(op->mem_addr & ~3);
152 | }else
153 | {
154 | val = word;
155 | }
156 |
157 | }else
158 | {
159 | --waiting_data;
160 | return;
161 | }
162 | }
163 |
164 |
165 | switch (op->opcode) {
166 | case OP_LW:
167 | case OP_LH:
168 | case OP_LHU:
169 | case OP_LB:
170 | case OP_LBU:
171 | {
172 | /* extract needed value */
173 | op->reg_dst_value_ready = 1;
174 | if (op->opcode == OP_LW) {
175 | op->reg_dst_value = val;
176 | }
177 | else if (op->opcode == OP_LH || op->opcode == OP_LHU) {
178 | if (op->mem_addr & 2)
179 | val = (val >> 16) & 0xFFFF;
180 | else
181 | val = val & 0xFFFF;
182 |
183 | if (op->opcode == OP_LH)
184 | val |= (val & 0x8000) ? 0xFFFF8000 : 0;
185 |
186 | op->reg_dst_value = val;
187 | }
188 | else if (op->opcode == OP_LB || op->opcode == OP_LBU) {
189 | switch (op->mem_addr & 3) {
190 | case 0:
191 | val = val & 0xFF;
192 | break;
193 | case 1:
194 | val = (val >> 8) & 0xFF;
195 | break;
196 | case 2:
197 | val = (val >> 16) & 0xFF;
198 | break;
199 | case 3:
200 | val = (val >> 24) & 0xFF;
201 | break;
202 | }
203 |
204 | if (op->opcode == OP_LB)
205 | val |= (val & 0x80) ? 0xFFFFFF80 : 0;
206 |
207 | op->reg_dst_value = val;
208 | }
209 | }
210 | break;
211 |
212 | case OP_SB:
213 | switch (op->mem_addr & 3) {
214 | case 0: val = (val & 0xFFFFFF00) | ((op->mem_value & 0xFF) << 0); break;
215 | case 1: val = (val & 0xFFFF00FF) | ((op->mem_value & 0xFF) << 8); break;
216 | case 2: val = (val & 0xFF00FFFF) | ((op->mem_value & 0xFF) << 16); break;
217 | case 3: val = (val & 0x00FFFFFF) | ((op->mem_value & 0xFF) << 24); break;
218 | }
219 | // mem_write_32(op->mem_addr & ~3, val);
220 | cache_data_write_val(op->mem_addr & ~3, val);
221 |
222 | break;
223 |
224 | case OP_SH:
225 | #ifdef DEBUG
226 | printf("SH: addr %08x val %04x old word %08x\n", op->mem_addr, op->mem_value & 0xFFFF, val);
227 | #endif
228 | if (op->mem_addr & 2)
229 | val = (val & 0x0000FFFF) | (op->mem_value) << 16;
230 | else
231 | val = (val & 0xFFFF0000) | (op->mem_value & 0xFFFF);
232 | #ifdef DEBUG
233 | printf("new word %08x\n", val);
234 | #endif
235 |
236 | // mem_write_32(op->mem_addr & ~3, val);
237 | cache_data_write_val(op->mem_addr & ~3, val);
238 | break;
239 |
240 | case OP_SW:
241 | val = op->mem_value;
242 |
243 | // mem_write_32(op->mem_addr & ~3, val);
244 | cache_data_write_val(op->mem_addr & ~3, val);
245 | break;
246 | }
247 |
248 | /* clear stage input and transfer to next stage */
249 | pipe.mem_op = NULL;
250 | pipe.wb_op = op;
251 | }
252 |
253 | void pipe_stage_execute()
254 | {
255 | // printf("ex\n");
256 | /* if a multiply/divide is in progress, decrement cycles until value is ready */
257 | if (pipe.multiplier_stall > 0)
258 | pipe.multiplier_stall--;
259 |
260 | /* if downstream stall, return (and leave any input we had) */
261 | if (pipe.mem_op != NULL)
262 | return;
263 |
264 | /* if no op to execute, return */
265 | if (pipe.execute_op == NULL)
266 | return;
267 |
268 | /* grab op and read sources */
269 | Pipe_Op *op = pipe.execute_op;
270 |
271 | /* read register values, and check for bypass; stall if necessary */
272 | int stall = 0;
273 | if (op->reg_src1 != -1) {
274 | if (op->reg_src1 == 0)
275 | op->reg_src1_value = 0;
276 | else if (pipe.mem_op && pipe.mem_op->reg_dst == op->reg_src1) {
277 | if (!pipe.mem_op->reg_dst_value_ready)
278 | stall = 1;
279 | else
280 | op->reg_src1_value = pipe.mem_op->reg_dst_value;
281 | }
282 | else if (pipe.wb_op && pipe.wb_op->reg_dst == op->reg_src1) {
283 | op->reg_src1_value = pipe.wb_op->reg_dst_value;
284 | }
285 | else
286 | op->reg_src1_value = pipe.REGS[op->reg_src1];
287 | }
288 | if (op->reg_src2 != -1) {
289 | if (op->reg_src2 == 0)
290 | op->reg_src2_value = 0;
291 | else if (pipe.mem_op && pipe.mem_op->reg_dst == op->reg_src2) {
292 | if (!pipe.mem_op->reg_dst_value_ready)
293 | stall = 1;
294 | else
295 | op->reg_src2_value = pipe.mem_op->reg_dst_value;
296 | }
297 | else if (pipe.wb_op && pipe.wb_op->reg_dst == op->reg_src2) {
298 | op->reg_src2_value = pipe.wb_op->reg_dst_value;
299 | }
300 | else
301 | op->reg_src2_value = pipe.REGS[op->reg_src2];
302 | }
303 |
304 | /* if bypassing requires a stall (e.g. use immediately after load),
305 | * return without clearing stage input */
306 | if (stall)
307 | return;
308 |
309 | /* execute the op */
310 | switch (op->opcode) {
311 | case OP_SPECIAL:
312 | op->reg_dst_value_ready = 1;
313 | switch (op->subop) {
314 | case SUBOP_SLL:
315 | op->reg_dst_value = op->reg_src2_value << op->shamt;
316 | break;
317 | case SUBOP_SLLV:
318 | op->reg_dst_value = op->reg_src2_value << op->reg_src1_value;
319 | break;
320 | case SUBOP_SRL:
321 | op->reg_dst_value = op->reg_src2_value >> op->shamt;
322 | break;
323 | case SUBOP_SRLV:
324 | op->reg_dst_value = op->reg_src2_value >> op->reg_src1_value;
325 | break;
326 | case SUBOP_SRA:
327 | op->reg_dst_value = (int32_t)op->reg_src2_value >> op->shamt;
328 | break;
329 | case SUBOP_SRAV:
330 | op->reg_dst_value = (int32_t)op->reg_src2_value >> op->reg_src1_value;
331 | break;
332 | case SUBOP_JR:
333 | case SUBOP_JALR:
334 | op->reg_dst_value = op->pc + 4;
335 | op->branch_dest = op->reg_src1_value;
336 | op->branch_taken = 1;
337 | break;
338 |
339 | case SUBOP_MULT:
340 | {
341 | /* we set a result value right away; however, we will
342 | * model a stall if the program tries to read the value
343 | * before it's ready (or overwrite HI/LO). Also, if
344 | * another multiply comes down the pipe later, it will
345 | * update the values and re-set the stall cycle count
346 | * for a new operation.
347 | */
348 | int64_t val = (int64_t)((int32_t)op->reg_src1_value) * (int64_t)((int32_t)op->reg_src2_value);
349 | uint64_t uval = (uint64_t)val;
350 | pipe.HI = (uval >> 32) & 0xFFFFFFFF;
351 | pipe.LO = (uval >> 0) & 0xFFFFFFFF;
352 |
353 | /* four-cycle multiplier latency */
354 | pipe.multiplier_stall = 4;
355 | }
356 | break;
357 | case SUBOP_MULTU:
358 | {
359 | uint64_t val = (uint64_t)op->reg_src1_value * (uint64_t)op->reg_src2_value;
360 | pipe.HI = (val >> 32) & 0xFFFFFFFF;
361 | pipe.LO = (val >> 0) & 0xFFFFFFFF;
362 |
363 | /* four-cycle multiplier latency */
364 | pipe.multiplier_stall = 4;
365 | }
366 | break;
367 |
368 | case SUBOP_DIV:
369 | if (op->reg_src2_value != 0) {
370 |
371 | int32_t val1 = (int32_t)op->reg_src1_value;
372 | int32_t val2 = (int32_t)op->reg_src2_value;
373 | int32_t div, mod;
374 |
375 | div = val1 / val2;
376 | mod = val1 % val2;
377 |
378 | pipe.LO = div;
379 | pipe.HI = mod;
380 | } else {
381 | // really this would be a div-by-0 exception
382 | pipe.HI = pipe.LO = 0;
383 | }
384 |
385 | /* 32-cycle divider latency */
386 | pipe.multiplier_stall = 32;
387 | break;
388 |
389 | case SUBOP_DIVU:
390 | if (op->reg_src2_value != 0) {
391 | pipe.HI = (uint32_t)op->reg_src1_value % (uint32_t)op->reg_src2_value;
392 | pipe.LO = (uint32_t)op->reg_src1_value / (uint32_t)op->reg_src2_value;
393 | } else {
394 | /* really this would be a div-by-0 exception */
395 | pipe.HI = pipe.LO = 0;
396 | }
397 |
398 | /* 32-cycle divider latency */
399 | pipe.multiplier_stall = 32;
400 | break;
401 |
402 | case SUBOP_MFHI:
403 | /* stall until value is ready */
404 | if (pipe.multiplier_stall > 0)
405 | return;
406 |
407 | op->reg_dst_value = pipe.HI;
408 | break;
409 | case SUBOP_MTHI:
410 | /* stall to respect WAW dependence */
411 | if (pipe.multiplier_stall > 0)
412 | return;
413 |
414 | pipe.HI = op->reg_src1_value;
415 | break;
416 |
417 | case SUBOP_MFLO:
418 | /* stall until value is ready */
419 | if (pipe.multiplier_stall > 0)
420 | return;
421 |
422 | op->reg_dst_value = pipe.LO;
423 | break;
424 | case SUBOP_MTLO:
425 | /* stall to respect WAW dependence */
426 | if (pipe.multiplier_stall > 0)
427 | return;
428 |
429 | pipe.LO = op->reg_src1_value;
430 | break;
431 |
432 | case SUBOP_ADD:
433 | case SUBOP_ADDU:
434 | op->reg_dst_value = op->reg_src1_value + op->reg_src2_value;
435 | break;
436 | case SUBOP_SUB:
437 | case SUBOP_SUBU:
438 | op->reg_dst_value = op->reg_src1_value - op->reg_src2_value;
439 | break;
440 | case SUBOP_AND:
441 | op->reg_dst_value = op->reg_src1_value & op->reg_src2_value;
442 | break;
443 | case SUBOP_OR:
444 | op->reg_dst_value = op->reg_src1_value | op->reg_src2_value;
445 | break;
446 | case SUBOP_NOR:
447 | op->reg_dst_value = ~(op->reg_src1_value | op->reg_src2_value);
448 | break;
449 | case SUBOP_XOR:
450 | op->reg_dst_value = op->reg_src1_value ^ op->reg_src2_value;
451 | break;
452 | case SUBOP_SLT:
453 | op->reg_dst_value = ((int32_t)op->reg_src1_value <
454 | (int32_t)op->reg_src2_value) ? 1 : 0;
455 | break;
456 | case SUBOP_SLTU:
457 | op->reg_dst_value = (op->reg_src1_value < op->reg_src2_value) ? 1 : 0;
458 | break;
459 | }
460 | break;
461 |
462 | case OP_BRSPEC:
463 | switch (op->subop) {
464 | case BROP_BLTZ:
465 | case BROP_BLTZAL:
466 | if ((int32_t)op->reg_src1_value < 0) op->branch_taken = 1;
467 | break;
468 |
469 | case BROP_BGEZ:
470 | case BROP_BGEZAL:
471 | if ((int32_t)op->reg_src1_value >= 0) op->branch_taken = 1;
472 | break;
473 | }
474 | break;
475 |
476 | case OP_BEQ:
477 | if (op->reg_src1_value == op->reg_src2_value) op->branch_taken = 1;
478 | break;
479 |
480 | case OP_BNE:
481 | if (op->reg_src1_value != op->reg_src2_value) op->branch_taken = 1;
482 | break;
483 |
484 | case OP_BLEZ:
485 | if ((int32_t)op->reg_src1_value <= 0) op->branch_taken = 1;
486 | break;
487 |
488 | case OP_BGTZ:
489 | if ((int32_t)op->reg_src1_value > 0) op->branch_taken = 1;
490 | break;
491 |
492 | case OP_ADDI:
493 | case OP_ADDIU:
494 | op->reg_dst_value_ready = 1;
495 | op->reg_dst_value = op->reg_src1_value + op->se_imm16;
496 | break;
497 | case OP_SLTI:
498 | op->reg_dst_value_ready = 1;
499 | op->reg_dst_value = (int32_t)op->reg_src1_value < (int32_t)op->se_imm16 ? 1 : 0;
500 | break;
501 | case OP_SLTIU:
502 | op->reg_dst_value_ready = 1;
503 | op->reg_dst_value = (uint32_t)op->reg_src1_value < (uint32_t)op->se_imm16 ? 1 : 0;
504 | break;
505 | case OP_ANDI:
506 | op->reg_dst_value_ready = 1;
507 | op->reg_dst_value = op->reg_src1_value & op->imm16;
508 | break;
509 | case OP_ORI:
510 | op->reg_dst_value_ready = 1;
511 | op->reg_dst_value = op->reg_src1_value | op->imm16;
512 | break;
513 | case OP_XORI:
514 | op->reg_dst_value_ready = 1;
515 | op->reg_dst_value = op->reg_src1_value ^ op->imm16;
516 | break;
517 | case OP_LUI:
518 | op->reg_dst_value_ready = 1;
519 | op->reg_dst_value = op->imm16 << 16;
520 | break;
521 |
522 | case OP_LW:
523 | case OP_LH:
524 | case OP_LHU:
525 | case OP_LB:
526 | case OP_LBU:
527 | op->mem_addr = op->reg_src1_value + op->se_imm16;
528 | break;
529 |
530 | case OP_SW:
531 | case OP_SH:
532 | case OP_SB:
533 | op->mem_addr = op->reg_src1_value + op->se_imm16;
534 | op->mem_value = op->reg_src2_value;
535 | break;
536 | }
537 |
538 | /* handle branch recoveries at this point */
539 | if (op->branch_taken)
540 | pipe_recover(3, op->branch_dest);
541 |
542 | /* remove from upstream stage and place in downstream stage */
543 | pipe.execute_op = NULL;
544 | pipe.mem_op = op;
545 | }
546 |
547 | void pipe_stage_decode()
548 | {
549 | /* if downstream stall, return (and leave any input we had) */
550 | if (pipe.execute_op != NULL)
551 | return;
552 |
553 | /* if no op to decode, return */
554 | if (pipe.decode_op == NULL)
555 | return;
556 |
557 | /* grab op and remove from stage input */
558 | Pipe_Op *op = pipe.decode_op;
559 | pipe.decode_op = NULL;
560 |
561 | /* set up info fields (source/dest regs, immediate, jump dest) as necessary */
562 | uint32_t opcode = (op->instruction >> 26) & 0x3F;
563 | uint32_t rs = (op->instruction >> 21) & 0x1F;
564 | uint32_t rt = (op->instruction >> 16) & 0x1F;
565 | uint32_t rd = (op->instruction >> 11) & 0x1F;
566 | uint32_t shamt = (op->instruction >> 6) & 0x1F;
567 | uint32_t funct1 = (op->instruction >> 0) & 0x1F;
568 | uint32_t funct2 = (op->instruction >> 0) & 0x3F;
569 | uint32_t imm16 = (op->instruction >> 0) & 0xFFFF;
570 | uint32_t se_imm16 = imm16 | ((imm16 & 0x8000) ? 0xFFFF8000 : 0);
571 | uint32_t targ = (op->instruction & ((1UL << 26) - 1)) << 2;
572 |
573 | op->opcode = opcode;
574 | op->imm16 = imm16;
575 | op->se_imm16 = se_imm16;
576 | op->shamt = shamt;
577 | // printf("0x%x\n",opcode);
578 | switch (opcode) {
579 | case OP_SPECIAL:
580 | /* all "SPECIAL" insts are R-types that use the ALU and both source
581 | * regs. Set up source regs and immediate value. */
582 | op->reg_src1 = rs;
583 | op->reg_src2 = rt;
584 | op->reg_dst = rd;
585 | op->subop = funct2;
586 | if (funct2 == SUBOP_SYSCALL) {
587 | op->reg_src1 = 2; // v0
588 | op->reg_src2 = 3; // v1
589 | }
590 | if (funct2 == SUBOP_JR || funct2 == SUBOP_JALR) {
591 | op->is_branch = 1;
592 | op->branch_cond = 0;
593 | }
594 |
595 | break;
596 |
597 | case OP_BRSPEC:
598 | /* branches that have -and-link variants come here */
599 | op->is_branch = 1;
600 | op->reg_src1 = rs;
601 | op->reg_src2 = rt;
602 | op->is_branch = 1;
603 | op->branch_cond = 1; /* conditional branch */
604 | op->branch_dest = op->pc + 4 + (se_imm16 << 2);
605 | op->subop = rt;
606 | if (rt == BROP_BLTZAL || rt == BROP_BGEZAL) {
607 | /* link reg */
608 | op->reg_dst = 31;
609 | op->reg_dst_value = op->pc + 4;
610 | op->reg_dst_value_ready = 1;
611 | }
612 | break;
613 |
614 | case OP_JAL:
615 | op->reg_dst = 31;
616 | op->reg_dst_value = op->pc + 4;
617 | op->reg_dst_value_ready = 1;
618 | op->branch_taken = 1;
619 | /* fallthrough */
620 | case OP_J:
621 | op->is_branch = 1;
622 | op->branch_cond = 0;
623 | op->branch_taken = 1;
624 | op->branch_dest = (op->pc & 0xF0000000) | targ;
625 | break;
626 |
627 | case OP_BEQ:
628 | case OP_BNE:
629 | case OP_BLEZ:
630 | case OP_BGTZ:
631 | /* ordinary conditional branches (resolved after execute) */
632 | op->is_branch = 1;
633 | op->branch_cond = 1;
634 | op->branch_dest = op->pc + 4 + (se_imm16 << 2);
635 | op->reg_src1 = rs;
636 | op->reg_src2 = rt;
637 | break;
638 |
639 | case OP_ADDI:
640 | case OP_ADDIU:
641 | case OP_SLTI:
642 | case OP_SLTIU:
643 | /* I-type ALU ops with sign-extended immediates */
644 | op->reg_src1 = rs;
645 | op->reg_dst = rt;
646 | break;
647 |
648 | case OP_ANDI:
649 | case OP_ORI:
650 | case OP_XORI:
651 | case OP_LUI:
652 | /* I-type ALU ops with non-sign-extended immediates */
653 | op->reg_src1 = rs;
654 | op->reg_dst = rt;
655 | break;
656 |
657 | case OP_LW:
658 | case OP_LH:
659 | case OP_LHU:
660 | case OP_LB:
661 | case OP_LBU:
662 | case OP_SW:
663 | case OP_SH:
664 | case OP_SB:
665 | /* memory ops */
666 | op->is_mem = 1;
667 | op->reg_src1 = rs;
668 | if (opcode == OP_LW || opcode == OP_LH || opcode == OP_LHU || opcode == OP_LB || opcode == OP_LBU) {
669 | /* load */
670 | op->mem_write = 0;
671 | op->reg_dst = rt;
672 | }
673 | else {
674 | /* store */
675 | op->mem_write = 1;
676 | op->reg_src2 = rt;
677 | }
678 | break;
679 | }
680 |
681 | /* we will handle reg-read together with bypass in the execute stage */
682 |
683 | /* place op in downstream slot */
684 | pipe.execute_op = op;
685 | }
686 |
687 | uint32_t inst;
688 |
689 | void pipe_stage_fetch()
690 | {
691 | /* if pipeline is stalled (our output slot is not empty), return */
692 | if (pipe.decode_op != NULL)
693 | return;
694 |
695 | /* Allocate an op and send it down the pipeline. */
696 | Pipe_Op *op = malloc(sizeof(Pipe_Op));
697 | memset(op, 0, sizeof(Pipe_Op));
698 | op->reg_src1 = op->reg_src2 = op->reg_dst = -1;
699 |
700 | if (waiting == 0) {
701 | inst = cache_read(pipe.PC);
702 | }
703 |
704 | if(waiting == 0) {
705 | if(inst == 0xffffffff) {
706 | op->instruction = mem_read_32(pipe.PC);
707 | } else {
708 | op->instruction = inst;
709 | }
710 | op->pc = pipe.PC;
711 | pipe.decode_op = op;
712 | /* update PC */
713 | pipe.PC += 4;
714 | } else {
715 | --waiting;
716 | op->instruction = 0x00000025;
717 | }
718 |
719 |
720 |
721 | stat_inst_fetch++;
722 | }
723 |
724 |
--------------------------------------------------------------------------------