Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
minseongg committed Sep 17, 2024
1 parent c1e8b6b commit c0677a1
Show file tree
Hide file tree
Showing 51 changed files with 38,634 additions and 734 deletions.
9 changes: 8 additions & 1 deletion doc/docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,14 @@

# Case Studies

- [CPU Core (5-Stage Pipelined)](./examples/cpu.md)
- [CPU Core (5-Stage Pipelined)](./examples/cpu/overview.md)
+ [Hazards](./examples/cpu/hazard.md)
+ [Implementation](./examples/cpu/implementation.md)
+ [Fetch](./examples/cpu/fetch.md)
+ [Decode](./examples/cpu/decode.md)
+ [Execute](./examples/cpu/exe.md)
+ [Memory](./examples/cpu/mem.md)
+ [Writeback](./examples/cpu/wb.md)
- [NPU Core (Based on Systolic Array)](./examples/npu.md)

# Appendix
Expand Down
557 changes: 0 additions & 557 deletions doc/docs/examples/cpu.md

This file was deleted.

116 changes: 116 additions & 0 deletions doc/docs/examples/cpu/decode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Decode stage

The decode stage mainly do the following things:

1. Decodes the instruction.
2. Reads the value of source registers.

It can be decomposed into combinators as follows ([code](https://github.com/kaist-cp/hazardflow/blob/main/hazardflow-designs/src/cpu/decode.rs)):

<p align="center">
<img src="../../figure/cpu-implementation-decode.svg" width=95% />
</p>

## Input and Output

The IO interface type of the decode stage is as follows:

### Ingress

It takes an ingress interface with type `I<VrH<FetEP, DecR>, { Dep::Demanding }>`.

You can check the explanation of `FetEP` and `DecR` in [here](fetch.md#egress).

### Egress

It returns an egress interface with type `I<VrH<DecEP, ExeR>, { Dep::Demanding }>`.

Each of `DecEP` and `ExeR` is defined as a struct with the following fields:

**DecEP** (in [decode.rs](https://github.com/kaist-cp/hazardflow/blob/main/hazardflow-designs/src/cpu/decode.rs)):

- `wb_info`: Writeback information which contains the writeback address and selector.
- `br_info`: Branch information which contains the branch type, target address' base and offset.
- `alu_input`: ALU input.
- `mem_info`: Memory information.
- `csr_info`: CSR information.
- `is_illegal`: Indicates that the instruction is illegal or not.
- `pc`: PC.
- `debug_inst`: Instruction (for debugging purpose).

**ExeR** (in [exe.rs](https://github.com/kaist-cp/hazardflow/blob/main/hazardflow-designs/src/cpu/exe.rs)):

- `bypass_from_exe`: Bypassed data from the execute stage.
- `bypass_from_mem`: Bypassed data from the memory stage.
- `bypass_from_wb`: Bypassed data from the writeback stage.
- `stall`: Destination register address of load or CSR instruction in the execute stage.
- `redirect`: Redirection PC.
- `rf`: Register file.

## Behavior

Each combinator do the following things:

**M0** ([`map_resolver_inner`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.map_resolver_inner)):

- Constructs the ingress resolver of the decode stage.

**M1** ([`reg_fwd`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.reg_fwd)):

- Creates a pipelined stage before decoding the instruction.
- Sends a ready signal which indicates it will be free in the next cycle.

**M2** ([`map`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.map-1)):

- Decodes the instruction.

**M3** ([`map_resolver_block`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.map_resolver_block)):

- Stalls until the value of source registers are visible.

**M4** ([`filter_map_drop_with_r`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.filter_map_drop_with_r)):

- Reads the value of source registers and attaches them to the payload.
- Filters out the payload when the redirection happens.

<!--
<p align="center">
<img src="../../figure/decode.drawio.svg" />
</p>
**Calculate Ingress Resolver for Fetch Stage**
* Calculate the resolver from decode stage to fetch stage.
* Resolvers from later stages will be used here to calculate `pc_sel` and `if_kill`
<p align="center">
<img src="../../figure/decode_gen_resolver.drawio.svg" />
</p>
**Store The Instruction Memory Response and Decode The Instruction**
* We store the `imem` response into the latch.
* We decode the current `imem` response and calculate the instruction.
<p align="center">
<img src="../../figure/store_decode.drawio.svg" />
</p>
**Stall the Payload and Pass Back The Instruction**
* We need to stall the payload if certain certain hazards happen.
* We need to pass back the decoded instruction to previous combinators for calculating resolver.
<p align="center">
<img src="../../figure/stall_pass_back.drawio.svg" />
</p>
**Calculate the Egress Payload for Execution Stage**
* Calculate the payload for execution stage.
* Drop the payload if certain hazards happen.
<p align="center">
<img src="../../figure/decode_ep.drawio.svg" />
</p>
-->
127 changes: 127 additions & 0 deletions doc/docs/examples/cpu/exe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# Execute stage

The execute stage mainly do the following things:

1. Executes the ALU.
2. Resolves the branch misprediction.

It can be decomposed into combinators as follows ([code](https://github.com/kaist-cp/hazardflow/blob/main/hazardflow-designs/src/cpu/exe.rs)):

<p align="center">
<img src="../../figure/cpu-implementation-exe.svg" width=95% />
</p>

## Input and Output

The IO interface type of the execute stage is as follows:

### Ingress

It takes an ingress interface with type `I<VrH<DecEP, ExeR>, { Dep::Demanding }>`.

You can check the explanation of `DecEP` and `ExeR` in [here](decode.md#egress).

### Egress

It returns an egress interface with type `I<VrH<ExeEP, MemR>, { Dep::Demanding }>`.

Each of `ExeEP` and `MemR` is defined as a struct with the following fields:

**ExeEP** (in [exe.rs](https://github.com/kaist-cp/hazardflow/blob/main/hazardflow-designs/src/cpu/exe.rs)):

- `wb_info`: Writeback information which contains the writeback address and selector.
- `alu_out`: ALU output.
- `mem_info`: Memory information.
- `csr_info`: CSR information.
- `is_illegal`: Indicates that the instruction is illegal or not.
- `pc`: PC.
- `debug_inst`: Instruction (for debugging purpose).

**MemR** (in [mem.rs](https://github.com/kaist-cp/hazardflow/blob/main/hazardflow-designs/src/cpu/mem.rs)):

- `bypass_from_mem`: Bypassed data from the memory stage.
- `bypass_from_wb`: Bypassed data from the writeback stage.
- `redirect`: Redirection PC.
- `rf`: Register file.

## Behavior

Each combinator do the following things:

**M0** ([`map_resolver_inner`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.map_resolver_inner)):

- Resolves the branch misprediction based on the branch type and ALU output.
- Constructs the ingress resolver of the execute stage.
+ Attaches the bypassed data, stall, and redirection PC for resolving data hazards.

**M1** ([`reg_fwd`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.reg_fwd)):

- Creates a pipelined stage before executing the ALU.
- Sends a ready signal which indicates it will be free in the next cycle.

**M2** ([`map`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.map-1)):

- Executes the ALU.

**M3** ([`map_resolver_block_with_p`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.map_resolver_block_with_p)):

- Attaches the ALU output to the resolver signal for the redirection PC calculation.
- Stalls until the data hazards have been resolved.

**M4** ([`filter_map_drop_with_r_inner`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.filter_map_drop_with_r_inner)):

- Attaches the ALU output to the payload.
- Filters out the payload when the redirection happens.

<!--
The execution stage executes instruction from the decode stage,
calculates the payload passing to the memory stage,
and also calculates the resolver passing to the decode stage.
* The ingress payload is decode stage's egress payload `DecEP`.
* The ingress resolver is the resolvers from execute stage and later stages `(exe_r, mem_r, wb_r)`.
* The egress payload should contain necessary information for the memory stage `exe_ep`.
* The egress resolver contains the resolver from memory stage and write-back stage `(mem_r, wb_r)`.
**Calculate Ingress Resolver for Decode Stage**
* Calculate the execution stage resolver and pass it with `mem_r` and `wb_r` to the decode stage.
<p align="center">
<img src="../../figure/exe_resolver.drawio.svg" />
</p>
**Store the Decode Stage Egress Payload**
* Store the `dec_ep` into register for passing back to previous combinators for calculating `exe_r`.
<p align="center">
<img src="../../figure/exe_latch.drawio.svg" />
</p>
**Execute The Instruction**
* Execute the instruction and pass the `alu_out` to the next combinator.
<p align="center">
<img src="../../figure/exe_inst.drawio.svg" />
</p>
**Stall The Payload and Pass Back The Result of ALU**
* We need to stall the payload if certain certain hazards happen.
* We need to pass back the result of ALU `alu_out` to previous combinators for calculating resolver.
<p align="center">
<img src="../../figure/stall_exe.drawio.svg" />
</p>
**Calculate The Payload For Memory Stage**
* Calculate the payload for the memory stage.
* Drop the payload if certain hazards happen.
<p align="center">
<img src="../../figure/exe_ep.drawio.svg" />
</p>
-->
84 changes: 84 additions & 0 deletions doc/docs/examples/cpu/fetch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# Fetch stage

The fetch stage mainly do the following things:

1. Calculates the next PC for the upcoming instruction.
2. Accesses IMEM to retrieve the instruction bytecode.

It can be decomposed into combinators as follows ([code](https://github.com/kaist-cp/hazardflow/blob/main/hazardflow-designs/src/cpu/fetch.rs)):

<p align="center">
<img src="../../figure/cpu-implementation-fetch.svg" width=95% />
</p>

## Input and Output

The IO interface type of the fetch stage is as follows:

### Ingress

This is the first stage, it does not take any ingress interface.

### Egress

It returns an egress interface with type `I<VrH<FetEP, DecR>, { Dep::Demanding }>`.

Each of `FetEP` and `DecR` is defined as a struct with the following fields:

**FetEP** (in [fetch.rs](https://github.com/kaist-cp/hazardflow/blob/main/hazardflow-designs/src/cpu/fetch.rs)):

- `imem_resp`: IMEM response which contains the address (PC) and the data (inst bytecode).

**DecR** (in [decode.rs](https://github.com/kaist-cp/hazardflow/blob/main/hazardflow-designs/src/cpu/decode.rs)):

- `redirect`: Represents the redirection PC when the control hazard occurs.

## Behavior

Each combinator do the following things:

**M0** ([`source_drop`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.source_drop)):

- Forwards the current IMEM response and the redirection PC from the resolver to the payload.

**M1** ([`filter_map`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.filter_map-1)):

- Calculates the next PC based on the incoming payload.
+ If the redirection PC exists, go to it.
+ Otherwise, go to the next sequential address (PC + 4).

**M2** ([`reg_fwd_with_init`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.reg_fwd_with_init)):

- Creates a pipelined stage before accessing IMEM by storing the next PC in a register.
- When the circuit is reset, it is initialized with the designated start address (`START_ADDR`).

**M3** ([`map`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.map-1) + [`comb`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/interface/trait.Interface.html#method.comb) + [`map`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.map-1)):

- Constructs the IMEM request with `map` combinator.
- Accesses the external IMEM module to fetch the instruction bytecode with `comb` combinator.
+ We use an asynchronous memory for memory, it provide the response in the same cycle.
+ We used [`attach_resolver`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/valid_ready/fn.attach_resolver.html) module combinator to attach additional resolver to the IMEM.
- Deconstructs the IMEM response with `map` combinator.

**M4** ([`map_resolver_drop_with_p`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.map_resolver_drop_with_p)):

- Attaches the IMEM response to the resolver signal for the next PC calculation.
- Turns on the ready signal when control hazard occurs to extract the payload from **M2**.

**M5** ([`filter_map_drop_with_r_inner`](https://kaist-cp.github.io/hazardflow/docs/hazardflow_designs/std/hazard/struct.I.html#method.filter_map_drop_with_r_inner)):

- Filters out the payload when the redirection happens.

<!--
<p align="center">
<img src="../../figure/nextpc.drawio.svg" />
</p>
<p align="center">
<img src="../../figure/store_extract_pc.drawio.svg" />
</p>
<p align="center">
<img src="../../figure/req_imem.drawio.svg" />
</p>
-->
Loading

0 comments on commit c0677a1

Please sign in to comment.