-
Notifications
You must be signed in to change notification settings - Fork 13
C-extended fetch stage and instruction reader module #252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
SiddharthShroff-dotcom
wants to merge
17
commits into
main
Choose a base branch
from
C-extended-fetcher
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 16 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
75c8c8e
C-extended fetch stage and instruction reader module
SiddharthShroff-dotcom 20f20bf
Temporary placeholder for C decompressor module
SiddharthShroff-dotcom 1d949fb
formatting changes and unused wires
SiddharthShroff-dotcom 47f253c
Fix svlint style issues
SiddharthShroff-dotcom 4006a10
Add instruction reader to DE1-SoC synthesis
SiddharthShroff-dotcom 5a4c63d
fixed formatting of instruction reader to pass checks
SiddharthShroff-dotcom 478ac6c
Clean final svlint formatting issues
SiddharthShroff-dotcom 5c83bc4
Update instruction_reader.sv
SiddharthShroff-dotcom 166b3d1
Fix final lint whitespace issues
SiddharthShroff-dotcom 4d9b0cf
Fix final fetch stage indentation
SiddharthShroff-dotcom f26e3b1
Add passing RVC fetch testbenches
SiddharthShroff-dotcom 4aec683
Style-fix RVC fetch testbenches
SiddharthShroff-dotcom fc6db13
Fix RVC fetch testbench lint warnings
SiddharthShroff-dotcom 958a4f1
Move instruction reader to ext flder and remove lint UNUSED SIGNAL co…
SiddharthShroff-dotcom 6003888
Gate compressed fetch behind C extension
SiddharthShroff-dotcom 089bec8
Enable C extension for RVC fetch tests
SiddharthShroff-dotcom 0ea56af
Fix RVC split fetch handling under stall and flush
SiddharthShroff-dotcom File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,182 @@ | ||
| `include "src/timescale.svh" | ||
| `include "src/headers/params.svh" | ||
| `include "src/headers/types.svh" | ||
| `include "src/interfaces/if_to_id_if.svh" | ||
| `include "src/interfaces/ex_to_if_if.svh" | ||
| module fetch_compressed | ||
| ( output if_to_id_t if_to_id | ||
| , input ex_to_if_t ex_to_if | ||
| , input wire clk | ||
| , input wire reset | ||
| , input wire stall_f | ||
| , input wire flush_f | ||
| , output addr_t imem__address | ||
| , input data_t imem__data | ||
| ); | ||
|
|
||
| addr_t pc_prev; | ||
| addr_t pc_cur; | ||
| addr_t pc_next; | ||
| // RVC/C-extension fetch helpers. | ||
|
|
||
| instr_t stalled_instr; | ||
| logic stalled_instr_valid; | ||
|
|
||
| instr_t final_instr; | ||
| logic final_illegal; | ||
| instr_t decompressed_instr; | ||
| logic compressed_illegal; | ||
| logic reader_inst_is_compressed; | ||
| logic reader_inst_is_split; | ||
| instr_t reader_instr_raw; | ||
| addr_t reader_instr_pc; | ||
| addr_t reader_next_pc; | ||
| //state bit to indicate : currently waiting to finish a split instruction | ||
| logic split_wait_valid; | ||
| data_t split_wait_cur_word; | ||
| addr_t split_wait_pc; | ||
| logic need_split_wait; | ||
| logic buffer_after_split; | ||
| logic hold_pc_for_split_buffer; | ||
| //a safety instruction that doesnt do anything | ||
| //outputted when we need to wait an extra cycle to fetch a split 32-bit instruction | ||
| localparam instr_t NOP = 32'h00000013; | ||
| //for buffer for when two compressed instructions are back to back, | ||
| // and the second one is in the same 32-bit word as the first one, | ||
| //so we can just buffer the whole word and then read the second instruction | ||
| //from it without needing to fetch again from memory. | ||
| //This is an optimization to avoid unnecessary memory accesses for | ||
| //consecutive compressed instructions that happen to be in the same word. | ||
| logic buffered_word_valid; | ||
| data_t buffered_word; | ||
| addr_t buffered_pc; | ||
| // buffered_pc tells the reader which halfword inside buffered_word to use. | ||
| logic use_buffer; | ||
| logic buffer_next_same_word; | ||
| addr_t reader_pc_i; | ||
| data_t reader_cur_word_i; | ||
| data_t reader_next_word; | ||
|
|
||
| wire unused = &{ | ||
| ex_to_if.pc_old | ||
| , ex_to_if.imm_ext | ||
| , final_illegal | ||
| }; | ||
|
|
||
| always_comb | ||
| case (ex_to_if.pc_src) | ||
| // PC_SRC__INCREMENT: pc_next = pc_cur + 32'h4; | ||
| PC_SRC__INCREMENT: pc_next = {pc_cur[31:2], 2'b00} + 32'd4; | ||
| PC_SRC__ALU_RESULT: pc_next = ex_to_if.pc_target; | ||
| default: pc_next = 32'hx; | ||
| endcase | ||
|
|
||
| always_ff @ (posedge clk) | ||
| if (reset) | ||
| {stalled_instr, stalled_instr_valid} <= {instr_t'(0) , 1'b0}; | ||
| else if (flush_f) | ||
| {stalled_instr, stalled_instr_valid} <= {stalled_instr, 1'b0}; | ||
| else if (stall_f && !stalled_instr_valid) | ||
| {stalled_instr, stalled_instr_valid} <= {imem__data , 1'b1}; | ||
| else if (!stall_f && stalled_instr_valid) | ||
| {stalled_instr, stalled_instr_valid} <= {stalled_instr, 1'b0}; | ||
|
|
||
|
|
||
| //assign imem__address = pc_cur; | ||
| assign imem__address = {pc_cur[31:2], 2'b00}; | ||
|
|
||
| instruction_reader u_reader | ||
| ( .pc_i (reader_pc_i) | ||
| , .cur_word_i (reader_cur_word_i) | ||
| , .next_word_i (reader_next_word) | ||
| , .instr_raw_o (reader_instr_raw) | ||
| , .instr_pc_o (reader_instr_pc) | ||
| , .instr_next_pc_o (reader_next_pc) | ||
| , .instr_is_compressed_o (reader_inst_is_compressed) | ||
| , .instr_is_split_o (reader_inst_is_split) | ||
| ); | ||
| // TODO: Replace with real compressed decoder once C decompressor module is merged. | ||
| // For now, compressed instructions are converted to NOP so fetch-stage integration builds. | ||
| assign decompressed_instr = NOP; | ||
| assign compressed_illegal = 1'b0; | ||
| always_ff @ (posedge clk) | ||
| if (reset) | ||
| pc_cur <= addr_t'(0); | ||
| else if (!stall_f && !hold_pc_for_split_buffer) | ||
| pc_cur <= pc_next; | ||
| always_ff @ (posedge clk) | ||
| if (reset) | ||
| pc_prev <= addr_t'(0); | ||
| else if (!stall_f && !hold_pc_for_split_buffer) | ||
| pc_prev <= pc_cur; | ||
| always_ff @ (posedge clk) | ||
| if (reset || flush_f) | ||
| {split_wait_valid, split_wait_cur_word, split_wait_pc} | ||
| <= {1'b0, data_t'(0), addr_t'(0)}; | ||
| else if (!stall_f) | ||
| if (split_wait_valid) | ||
| split_wait_valid <= 1'b0; | ||
| else if (need_split_wait) | ||
| {split_wait_valid, split_wait_cur_word, split_wait_pc} | ||
| <= {1'b1, reader_cur_word_i, reader_instr_pc}; | ||
| always_ff @ (posedge clk) | ||
| if (reset || flush_f) | ||
| {buffered_word_valid, buffered_word, buffered_pc} | ||
| <= {1'b0, data_t'(0), addr_t'(0)}; | ||
| else if (!stall_f) | ||
| if (buffer_after_split) | ||
| {buffered_word_valid, buffered_word, buffered_pc} | ||
| <= {1'b1, imem__data, reader_next_pc}; | ||
| else if (use_buffer) | ||
| buffered_word_valid <= 1'b0; | ||
| else if (buffer_next_same_word) | ||
| {buffered_word_valid, buffered_word, buffered_pc} | ||
| <= {1'b1, reader_cur_word_i, reader_next_pc}; | ||
| /* | ||
| // If the next instruction we need to fetch is in the same word | ||
| //as the current instruction, buffer it for the next cycle. | ||
| //this case happens when we have a compressed instruction followed by another | ||
| //instruction (compressed or the start of a split 32-bit instruction) that starts in | ||
| //the same 32-bit word | ||
| */ | ||
| assign use_buffer = buffered_word_valid; | ||
| assign reader_pc_i = | ||
| split_wait_valid ? split_wait_pc : | ||
| use_buffer ? buffered_pc : | ||
| pc_prev; | ||
| assign reader_cur_word_i = | ||
| split_wait_valid ? split_wait_cur_word : | ||
| use_buffer ? buffered_word : | ||
| stalled_instr_valid ? data_t'(stalled_instr) : | ||
| imem__data; | ||
| assign reader_next_word = | ||
| (split_wait_valid || use_buffer) ? imem__data : data_t'(0); | ||
| assign buffer_next_same_word = | ||
| reader_inst_is_compressed && | ||
| (reader_next_pc[31:2] == reader_instr_pc[31:2]); | ||
| //Only insert the wait bubble the FIRST time you discover the split. | ||
| //Do not insert another bubble when you are already completing it. | ||
| assign need_split_wait = | ||
| reader_inst_is_split && !split_wait_valid; | ||
| //I just completed a split instruction, and the next instruction starts inside | ||
| //the next word that just arrived. Save that word for the next cycle. | ||
| assign buffer_after_split = | ||
| split_wait_valid && | ||
| reader_inst_is_split && | ||
| (reader_next_pc[31:2] == (reader_instr_pc[31:2] + 30'd1)); | ||
| //prevents the memory fetch PC from advancing too far while you | ||
| //consume the buffered instruction | ||
| assign hold_pc_for_split_buffer = | ||
| buffer_after_split; | ||
| assign final_instr = | ||
| reader_inst_is_compressed ? decompressed_instr : reader_instr_raw; | ||
| assign final_illegal = | ||
| reader_inst_is_compressed && compressed_illegal; | ||
| //final output to decode stage | ||
| assign if_to_id.instruction = | ||
| need_split_wait ? NOP : final_instr; | ||
| assign if_to_id.pc_cur = reader_instr_pc; | ||
| assign if_to_id.pc_plus_4 = reader_next_pc; | ||
|
|
||
|
|
||
| endmodule |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| `include "src/timescale.svh" | ||
| `include "src/headers/params.svh" | ||
| `include "src/headers/types.svh" | ||
|
|
||
| module instruction_reader | ||
| ( input addr_t pc_i | ||
| , input data_t cur_word_i | ||
| , input data_t next_word_i | ||
| , output instr_t instr_raw_o | ||
| , output addr_t instr_pc_o | ||
| , output addr_t instr_next_pc_o | ||
| , output logic instr_is_compressed_o | ||
| , output logic instr_is_split_o | ||
| ); | ||
|
|
||
| wire unused_next_word = | ||
| &{1'b0, next_word_i[31:16]}; | ||
| logic [15:0] selected_halfword; | ||
| logic selected_is_32b; | ||
| assign selected_halfword = | ||
| pc_i[1] ? cur_word_i[31:16] : cur_word_i[15:0]; | ||
| assign selected_is_32b = | ||
| selected_halfword[1:0] == 2'b11; | ||
| assign instr_pc_o = | ||
| pc_i; | ||
| assign instr_is_compressed_o = | ||
| !selected_is_32b; | ||
| assign instr_is_split_o = | ||
| selected_is_32b && pc_i[1]; | ||
| assign instr_next_pc_o = | ||
| pc_i + (instr_is_compressed_o ? 32'd2 : 32'd4); | ||
| assign instr_raw_o = | ||
| instr_is_compressed_o ? {16'b0, selected_halfword} : | ||
| instr_is_split_o ? {next_word_i[15:0], cur_word_i[31:16]} : | ||
| cur_word_i; | ||
| endmodule | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.