Skip to content

Commit 151224d

Browse files
authored
Merge pull request #49 from amichai-bd/roman_branch
add mini_core ctrl.md ducumentation
2 parents 468e068 + 770cb5b commit 151224d

File tree

4 files changed

+217
-5
lines changed

4 files changed

+217
-5
lines changed

docs/rvc/common/ctrl.md

Lines changed: 202 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,202 @@
1-
ctrl.md
1+
# ctrl
2+
## mini_core controller
3+
4+
- After you understood the mini_core architecture, you can start to understand the mini_core controller.
5+
- The mini_core controller is the main module of the mini_core implemented as a combination logic.
6+
- The controller is a part of Q101H stage of the pipeline.
7+
8+
- The controller goals are:
9+
1) Create all control signals, enable signals and select signal for each stage of the pipeline in the data path.
10+
2) Responsible for the control hazard and Load hazard detection.
11+
3) Get the instruction from I_MEM and use the decoder to set the Ctrl Bits.
12+
4) Construct the Immediate types.
13+
5) Use the rs1 & rs2 (RegSrc) to read the Register file data.
14+
6) Flush pipe line in case of branch or jump.
15+
16+
17+
18+
### Instantiation of mini_core controller in mini_core.sv
19+
20+
```
21+
mini_core_ctrl mini_core_ctrl (
22+
.Rst (Rst ), //input
23+
.Clock (Clock ), //input
24+
// input instruction
25+
.PreInstructionQ101H (PreInstructionQ101H), //input
26+
.PcQ101H (PcQ101H), // output logic [31:0] PcQ101H
27+
// input feedback from data path
28+
.BranchCondMetQ102H (BranchCondMetQ102H), //input
29+
.DMemReady (DMemReady), //input
30+
// ready signals for "back-pressure" - use as the enable for the pipe stage sample
31+
.ReadyQ100H (ReadyQ100H), // output
32+
.ReadyQ101H (ReadyQ101H), // output
33+
.ReadyQ102H (ReadyQ102H), // output
34+
.ReadyQ103H (ReadyQ103H), // output
35+
.ReadyQ104H (ReadyQ104H), // output
36+
// output ctrl signals
37+
.CtrlIf (CtrlIf ), //output
38+
.CtrlRf (CtrlRf ), //output
39+
.CtrlExe (CtrlExe ), //output
40+
.CtrlMem (CtrlMem ), //output
41+
.CtrlWb (CtrlWb ), //output
42+
// output data path signals
43+
.ImmediateQ101H (ImmediateQ101H ) //output
44+
);
45+
```
46+
47+
### Signal description
48+
- `preInstructionQ101H:` That signal is an input to mini_core controller. It is the instruction that comes from instruction memory.
49+
- `BranchCondMetQ102H:` That signal comes from Q102H stage and indicates if the branch condition is met. [Click here](docs/rvc/common/exe.md) to learn more.
50+
- `CtrIf, CtrlRf, CtrlExe, CtrlMem, CtrlWb:` These signals are output from mini_core controller. They are the control signals for each stage of the pipeline. Those signals are a part of `typedef struct packed named t_ctrl_if, t_ctrl_rf, t_ctrl_exe, t_ctrl_mem, t_ctrl_wb` (see mini_core_pkg.vh file) variables. We saw all of them in the previous sections.
51+
52+
### mini_core controller module mini_core_ctrl.sv
53+
54+
- The full code of the mini_core controller located at `/src/mini_core/mini_core_ctrl.sv`.
55+
56+
### Load Hazard
57+
58+
- A load hazard is not the same as a data hazard we talked about before in the execution stage. A data hazard happens when the data we want is in the pipeline but not in the right place yet. On the other hand, a load hazard occurs when we need data right now, but it hasn't been figured out yet. In these situations, we have to stall (stop) the pipeline and wait until the data becomes available.
59+
- Lets have a look at the following instruction that causes load hazard
60+
61+
```
62+
lw x1, imm(x2) #Q102H
63+
add x3, x1, x4 #Q101H
64+
```
65+
In the second instruction we need the data from the first instruction, but the data is not ready yet. We have to stall the pipeline and wait until the data becomes available.
66+
67+
- The following code shows how we detect load hazard in the mini_core controller is detected.
68+
69+
```
70+
assign LoadHzrdDetectQ101H = Rst ? 1'b0 :
71+
((PreRegSrc1Q101H == CtrlQ102H.RegDst) && (CtrlQ102H.Opcode == LOAD)) ? 1'b1:
72+
((PreRegSrc2Q101H == CtrlQ102H.RegDst) && (CtrlQ102H.Opcode == LOAD)) ? 1'b1:
73+
1'b0;
74+
```
75+
- Note that load hazard detection is done in Q101H stage. We compare the destination register of the previous instruction located in Q102H stage with the source registers of the current instruction located Q101H stage. If the previous instruction is a load instruction and the destination register of the previous instruction is the same as the source register of the current instruction, then we have a load hazard. In this case we have to stall the pipeline and wait until the data becomes available.
76+
77+
- To solve that problem we do the following things:
78+
1) Stall Pc in Q100H stage
79+
2) Disenable IF/ID register
80+
```
81+
assign ReadyQ101H = (!CoreFreeze) && !(LoadHzrdDetectQ101H); //
82+
assign ReadyQ100H = (!CoreFreeze) && ReadyQ101H;//
83+
```
84+
3) Inserting bubble (NOP)[^1] into Q101H stage.
85+
86+
```
87+
assign InstructionQ101H = flushQ102H ? NOP :
88+
flushQ103H ? NOP :
89+
LoadHzrdDetectQ101H ? NOP :
90+
PreInstructionQ101H;
91+
assign PreValidInstQ101H = flushQ102H ? 1'b0 :
92+
flushQ103H ? 1'b0 :
93+
LoadHzrdDetectQ101H ? 1'b0 :
94+
1'b1 ;
95+
```
96+
* flush signals will be discussed soon.
97+
98+
### Lets take a more detailed look
99+
100+
- Step1 - load hazard detected (happens concurrently with step 2)
101+
102+
| Q100H | Q101H | Q102H | Notes |
103+
|---------------------|-----------------|----------------|----------------------------|
104+
| Pc is stalled | add x3, x1, x4 | lw x1, imm(x2) | LoadHzrdDetectQ101H = 1'b1 |
105+
106+
- Step2 - response to load hazard
107+
108+
| Q100H | Q101H | Q102H | Notes |
109+
|----------------------------------------------------|----------------------|----------------|----------------------------|
110+
| Pc is stalled, still points on add x3, x1, x4 | addi x0, x0, 0 (NOP) | lw x1, imm(x2) | LoadHzrdDetectQ101H = 1'b1 |
111+
112+
- Step 3 - load hazard been handled
113+
114+
| Q100H | Q101H | Q102H | Q103H | Notes |
115+
|---------------------|-----------------|--------------------------|-----------------|---------------------------|
116+
| Enabe Pc | add x3, x1, x4 | addi x0, x0, 0 (NOP) | lw x1, imm(x2) |LoadHzrdDetectQ101H = 1'b0 |
117+
118+
- Step 4
119+
120+
| Q100H | Q101H | Q102H | Q103H | Q104H | Notes |
121+
|---------------------|-----------------|--------------------|-----------------------|---------------|------------|
122+
| Enabe Pc | new instruction | add x3, x1, x4 | addi x0, x0, 0 (NOP) |lw x1, imm(x2) | forwarding |
123+
124+
125+
126+
127+
### Control Hazard
128+
Control hazard occurs when we have a branch or jump instruction. In this case we have to flush the pipeline and start fetching instructions from the new address.
129+
130+
- Lets have a look at the following instruction that causes control hazard
131+
132+
case1 (No Control Hazard)
133+
```
134+
beq x1, x2, label1 #Q102H
135+
add x3, x1, x4 #Q101H
136+
add x5, x6, x7 #Q100H
137+
```
138+
if x1 != x2 then we execute the instruction in Q101H and Q100H as usual.
139+
140+
case2 (Control Hazard)
141+
```
142+
beq x1, x2, label1 #Q102H
143+
add x3, x1, x4 #Q101H
144+
add x5, x6, x7 #Q100H
145+
```
146+
147+
if x1 == x2 then it means that we have to flush the instructions in Q101H and Q100H and start fetching instructions from the new address.
148+
- flush in our context means that we have to change instructions on Q100H and Q101H into NOP's instruction into the pipeline. In this case we have to insert **2 NOP**.
149+
150+
```
151+
logic IndirectBranchQ102H;
152+
assign IndirectBranchQ102H = (CtrlQ102H.SelNextPcAluOutB && BranchCondMetQ102H) || (CtrlQ102H.SelNextPcAluOutJ);
153+
assign flushQ102H = IndirectBranchQ102H;
154+
`MAFIA_EN_DFF(flushQ103H , flushQ102H , Clock , ReadyQ103H)
155+
assign InstructionQ101H = flushQ102H ? NOP :
156+
flushQ103H ? NOP :
157+
LoadHzrdDetectQ101H ? NOP :
158+
PreInstructionQ101H;
159+
assign PreValidInstQ101H = flushQ102H ? 1'b0 :
160+
flushQ103H ? 1'b0 :
161+
LoadHzrdDetectQ101H ? 1'b0 :
162+
1'b1 ;
163+
```
164+
- IndirectBranchQ102H is a signal that indicates if we have a branch or jump instruction. If we have a branch or jump instruction then we have to flush the pipeline.
165+
- When flashQ102H is high, it means that we insert NOP into the actual Q101H stage. In order to insert another nop in the next cycle we use the following code to let flash moves threw the pipeline
166+
```
167+
`MAFIA_EN_DFF(flushQ103H , flushQ102H , Clock , ReadyQ103H)
168+
```
169+
170+
### Back pressure
171+
- Back pressure is a way we can stop the pipeline from moving forward. We use back pressure when we have a load hazard or memory access with read latency higher than 1. In this case we have to stop the pipeline and wait until the data becomes available.
172+
```
173+
assign ReadyQ104H = (!CoreFreeze);
174+
assign ReadyQ103H = (!CoreFreeze);
175+
assign ReadyQ102H = (!CoreFreeze);//
176+
assign ReadyQ101H = (!CoreFreeze) && !(LoadHzrdDetectQ101H); //
177+
assign ReadyQ100H = (!CoreFreeze) && ReadyQ101H;//
178+
```
179+
180+
181+
### Control signals goes threw the pipeline
182+
```
183+
// Sample the Ctrl bits though the pipe
184+
`MAFIA_EN_RST_DFF(CtrlQ102H, CtrlQ101H, Clock, ReadyQ102H, Rst )
185+
`MAFIA_EN_DFF (CtrlQ103H, CtrlQ102H, Clock, ReadyQ103H )
186+
`MAFIA_EN_DFF (CtrlQ104H, CtrlQ103H, Clock, ReadyQ104H )
187+
```
188+
189+
### ebreak detection
190+
- Used for debug purposes to indicates end of program.
191+
```
192+
logic ebreak_was_calledQ101H;
193+
assign ebreak_was_calledQ101H = (InstructionQ101H == 32'b000000000001_00000_000_00000_1110011);
194+
```
195+
196+
197+
198+
### note
199+
- there are more code in the mini_core controller that we didn't discuss here because its relatively simple and easy to understand. For example, the code that responsible for the immediate types construction, AluOp construction, etc.
200+
201+
202+
[^1]: NOP means addi x0, x0, 0 or 0x00000013H

docs/rvc/common/decode.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,9 @@
1-
decode.md
1+
# decode
2+
3+
- The decode stage is the second stage in the pipeline also know as Q101H stage (in our coding style). The goal of that stage is to decode the instruction and read the register file.
4+
- One module of the decode stage is the control module: `mini_core_ctrl.sv` and second one is the register file module: `mini_core_rf.sv`.
5+
- 1) Control module: The control module is responsible for decoding the instruction and determine the control signals. Please [click here](rvc/common/ctrl.md) for more information about the .
6+
- 2) Register file module: The register file has two read ports and one write port. Please [click here](rvc/common/rf.md) for more information about the register file.
7+
8+
- Due to the fact that both the PC register and the Instruction memory have a latency of 1 clock cycle, the output of the instruction memory is directly connected to that stage. This connection eliminates the need for an additional cycle within the core.
9+

docs/rvc/common/intro.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,19 @@
1111
|---------------|---------------------|--------------------|-------------------------------------------|----------------------------------|-------------------------------|
1212
| mini_core | mini_core.sv | | main file with all instantiations | | `/source/mini_core/` |
1313
| fetch | mini_core_if.sv | Q100H | fetch instruction from instruction memory | [if](rvc/common/if.md) | `/source/mini_core/` |
14-
| decode | mini_core_id.sv | Q101H | decode instruction and read register file | [decode](rvc/common/decode.md) | `/source/mini_core/` |
14+
| decode[^1] | mini_core_id.sv | Q101H | decode instruction and read register file | [decode](rvc/common/decode.md) | `/source/mini_core/` |
1515
| execution | mini_core_exe.sv | Q102H | execute instruction | [exe](rvc/common/exe.md) | `/source/mini_core/` |
1616
| memory | mini_core_mem.sv | Q103H | read/write memory | [mem_acs](rvc/common/mem_acs.md) | `/source/mini_core/` |
1717
| write_back | mini_core_wb.sv | Q104H | write back to register file | [wb](rvc/common/wb.md) | `/source/mini_core/` |
1818

19-
19+
2020
### Package files and macros locations
2121

2222
| file name | description | location |
2323
|-------------------|-------------------------------------------------------------------|----------------------------|
2424
| macros.sv | macros file, mostly DFF types | `/source/common/` |
2525
| mini_core_pkg.sv | enums, structs & parameters for the MAFIA core | `/source/mini_core/` |
2626
| common_pkg.sv | common parameters, structs, enums used in the many_core_project | `/source/common/` |
27-
| big_core_pkg.sv | common parameters, structs, enums used in the many_core_project | `/source/bog_core/` |
27+
| big_core_pkg.sv | common parameters, structs, enums used in the many_core_project | `/source/bog_core/` |
28+
29+
[^1]: Decode stage has two modules. The first one is the decoder module: `mini_core_id.sv` and second one is the register file module: `mini_core_rf.sv`

docs/rvc/common/wb.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# wb
22
## write back stage
33

4+
- The goal of that stage is to Select which data should be written back to the register file AluOut or DMemRdData.
45

56
### instantiation of mini_core_wb module in mini_core.sv
67

0 commit comments

Comments
 (0)