Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
M
MINOTAuR
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
MINOTAuR
MINOTAuR
Commits
511161d6
Commit
511161d6
authored
4 years ago
by
Alban Gruin
Browse files
Options
Downloads
Patches
Plain Diff
instr_queue: instr_fifo
Signed-off-by:
Alban Gruin
<
alban.gruin@irit.fr
>
parent
00451296
No related branches found
No related tags found
No related merge requests found
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
src/frontend/instr_fifo.sv
+166
-0
166 additions, 0 deletions
src/frontend/instr_fifo.sv
src/frontend/instr_queue.sv
+19
-21
19 additions, 21 deletions
src/frontend/instr_queue.sv
with
185 additions
and
21 deletions
src/frontend/instr_fifo.sv
0 → 100644
+
166
−
0
View file @
511161d6
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
// Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
module
instr_fifo
#(
parameter
bit
FALL_THROUGH
=
1'b0
,
// fifo is in fall-through mode
parameter
int
unsigned
DATA_WIDTH
=
32
,
// default data width if the fifo is of type logic
parameter
int
unsigned
DEPTH
=
8
,
// depth can be arbitrary from 0 to 2**32
parameter
type
dtype
=
logic
[
DATA_WIDTH
-
1
:
0
],
// DO NOT OVERWRITE THIS PARAMETER
parameter
int
unsigned
ADDR_DEPTH
=
(
DEPTH
>
1
)
?
$
clog2
(
DEPTH
)
:
1
)(
input
logic
clk_i
,
// Clock
input
logic
rst_ni
,
// Asynchronous reset active low
input
logic
flush_i
,
// flush the queue
input
logic
testmode_i
,
// test_mode to bypass clock gating
// status flags
output
logic
full_o
,
// queue is full
output
logic
empty_o
,
// queue is empty
output
logic
[
ADDR_DEPTH
-
1
:
0
]
usage_o
,
// fill pointer
// as long as the queue is not full we can push new data
input
dtype
data_i
,
// data to push into the queue
input
logic
push_i
,
// data is valid and can be pushed to the queue
// as long as the queue is not empty we can pop new elements
output
dtype
data_o
,
// output data
input
logic
pop_i
,
// pop head from queue
output
dtype
[
DEPTH
-
1
:
0
]
full_data_o
,
output
logic
[
DEPTH
-
1
:
0
]
full_data_valid_o
);
// local parameter
// FIFO depth - handle the case of pass-through, synthesizer will do constant propagation
localparam
int
unsigned
FIFO_DEPTH
=
(
DEPTH
>
0
)
?
DEPTH
:
1
;
// clock gating control
logic
gate_clock
;
// pointer to the read and write section of the queue
logic
[
ADDR_DEPTH
-
1
:
0
]
read_pointer_n
,
read_pointer_q
,
write_pointer_n
,
write_pointer_q
;
// keep a counter to keep track of the current queue status
logic
[
ADDR_DEPTH
:
0
]
status_cnt_n
,
status_cnt_q
;
// this integer will be truncated by the synthesis tool
// actual memory
dtype
[
FIFO_DEPTH
-
1
:
0
]
mem_n
,
mem_q
;
logic
[
FIFO_DEPTH
-
1
:
0
]
valid_n
,
valid_q
;
assign
usage_o
=
status_cnt_q
[
ADDR_DEPTH
-
1
:
0
];
if
(
DEPTH
==
0
)
begin
assign
empty_o
=
~
push_i
;
assign
full_o
=
~
pop_i
;
end
else
begin
assign
full_o
=
(
status_cnt_q
==
FIFO_DEPTH
[
ADDR_DEPTH
:
0
]);
assign
empty_o
=
(
status_cnt_q
==
0
)
&
~
(
FALL_THROUGH
&
push_i
);
end
// status flags
// read and write queue logic
always_comb
begin
:
read_write_comb
// default assignment
read_pointer_n
=
read_pointer_q
;
write_pointer_n
=
write_pointer_q
;
status_cnt_n
=
status_cnt_q
;
data_o
=
(
DEPTH
==
0
)
?
data_i
:
mem_q
[
read_pointer_q
];
mem_n
=
mem_q
;
gate_clock
=
1'b1
;
valid_n
=
valid_q
;
// push a new element to the queue
if
(
push_i
&&
~
full_o
)
begin
// push the data onto the queue
mem_n
[
write_pointer_q
]
=
data_i
;
valid_n
[
write_pointer_q
]
=
1'b1
;
// un-gate the clock, we want to write something
gate_clock
=
1'b0
;
// increment the write counter
if
(
write_pointer_q
==
FIFO_DEPTH
[
ADDR_DEPTH
-
1
:
0
]
-
1
)
write_pointer_n
=
'0
;
else
write_pointer_n
=
write_pointer_q
+
1
;
// increment the overall counter
status_cnt_n
=
status_cnt_q
+
1
;
end
if
(
pop_i
&&
~
empty_o
)
begin
// read from the queue is a default assignment
// but increment the read pointer...
valid_n
[
read_pointer_q
]
=
1'b0
;
if
(
read_pointer_n
==
FIFO_DEPTH
[
ADDR_DEPTH
-
1
:
0
]
-
1
)
read_pointer_n
=
'0
;
else
read_pointer_n
=
read_pointer_q
+
1
;
// ... and decrement the overall count
status_cnt_n
=
status_cnt_q
-
1
;
end
// keep the count pointer stable if we push and pop at the same time
if
(
push_i
&&
pop_i
&&
~
full_o
&&
~
empty_o
)
status_cnt_n
=
status_cnt_q
;
// FIFO is in pass through mode -> do not change the pointers
if
(
FALL_THROUGH
&&
(
status_cnt_q
==
0
)
&&
push_i
)
begin
data_o
=
data_i
;
if
(
pop_i
)
begin
status_cnt_n
=
status_cnt_q
;
read_pointer_n
=
read_pointer_q
;
write_pointer_n
=
write_pointer_q
;
end
end
end
// block: read_write_comb
assign
full_data_o
=
mem_q
;
assign
full_data_valid_o
=
valid_q
;
// sequential process
always_ff
@
(
posedge
clk_i
or
negedge
rst_ni
)
begin
if
(
~
rst_ni
)
begin
read_pointer_q
<=
'0
;
write_pointer_q
<=
'0
;
status_cnt_q
<=
'0
;
valid_q
<=
'0
;
end
else
begin
if
(
flush_i
)
begin
read_pointer_q
<=
'0
;
write_pointer_q
<=
'0
;
status_cnt_q
<=
'0
;
valid_q
<=
'0
;
end
else
begin
read_pointer_q
<=
read_pointer_n
;
write_pointer_q
<=
write_pointer_n
;
status_cnt_q
<=
status_cnt_n
;
valid_q
<=
valid_n
;
end
end
end
always_ff
@
(
posedge
clk_i
or
negedge
rst_ni
)
begin
if
(
~
rst_ni
)
begin
mem_q
<=
'0
;
end
else
if
(
!
gate_clock
)
begin
mem_q
<=
mem_n
;
end
end
// pragma translate_off
`ifndef
VERILATOR
initial
begin
assert
(
DEPTH
>
0
)
else
$
error
(
"DEPTH must be greater than 0."
);
end
full_write
:
assert
property
(
@
(
posedge
clk_i
)
disable
iff
(
~
rst_ni
)
(
full_o
|->
~
push_i
))
else
$
fatal
(
1
,
"Trying to push new data although the FIFO is full."
);
empty_read
:
assert
property
(
@
(
posedge
clk_i
)
disable
iff
(
~
rst_ni
)
(
empty_o
|->
~
pop_i
))
else
$
fatal
(
1
,
"Trying to pop data although the FIFO is empty."
);
`endif
// pragma translate_on
endmodule
// fifo_v3
This diff is collapsed.
Click to expand it.
src/frontend/instr_queue.sv
+
19
−
21
View file @
511161d6
...
...
@@ -123,7 +123,9 @@ module instr_queue (
logic
[
ariane_pkg
::
INSTR_PER_FETCH
-
1
:
0
]
input_is_mem
;
logic
output_is_mem
;
logic
[$
clog2
(
ariane_pkg
::
FETCH_FIFO_DEPTH
)
*
2
-
1
:
0
]
nr_mem_n
,
nr_mem_q
;
logic
[
ariane_pkg
::
INSTR_PER_FETCH
-
1
:
0
][
ariane_pkg
::
FETCH_FIFO_DEPTH
-
1
:
0
]
fifo_instr_valid
;
instr_data_t
[
ariane_pkg
::
INSTR_PER_FETCH
-
1
:
0
][
ariane_pkg
::
FETCH_FIFO_DEPTH
-
1
:
0
]
fifo_instr
;
logic
[
ariane_pkg
::
INSTR_PER_FETCH
-
1
:
0
][
ariane_pkg
::
FETCH_FIFO_DEPTH
-
1
:
0
]
fifo_instr_is_mem
;
assign
ready_o
=
~
(
|
instr_queue_full
)
&
~
full_address
;
...
...
@@ -231,6 +233,17 @@ module instr_queue (
(
instr_i
[
i
][
6
:
0
]
==
riscv
::
OpcodeAmo
));
end
for
(
genvar
i
=
0
;
i
<
ariane_pkg
::
INSTR_PER_FETCH
;
i
++
)
begin
for
(
genvar
j
=
0
;
j
<
ariane_pkg
::
FETCH_FIFO_DEPTH
;
j
++
)
begin
assign
fifo_instr_is_mem
[
i
][
j
]
=
fifo_instr_valid
[
i
][
j
]
&
((
fifo_instr
[
i
][
j
].
instr
[
6
:
0
]
==
riscv
::
OpcodeLoad
)
|
(
fifo_instr
[
i
][
j
].
instr
[
6
:
0
]
==
riscv
::
OpcodeLoadFp
)
|
(
fifo_instr
[
i
][
j
].
instr
[
6
:
0
]
==
riscv
::
OpcodeStore
)
|
(
fifo_instr
[
i
][
j
].
instr
[
6
:
0
]
==
riscv
::
OpcodeStoreFp
)
|
(
fifo_instr
[
i
][
j
].
instr
[
6
:
0
]
==
riscv
::
OpcodeAmo
));
end
end
assign
output_is_mem
=
fetch_entry_valid_o
&
((
fetch_entry_o
.
instruction
[
6
:
0
]
==
riscv
::
OpcodeLoad
)
|
(
fetch_entry_o
.
instruction
[
6
:
0
]
==
riscv
::
OpcodeLoadFp
)
|
...
...
@@ -238,21 +251,7 @@ module instr_queue (
(
fetch_entry_o
.
instruction
[
6
:
0
]
==
riscv
::
OpcodeStoreFp
)
|
(
fetch_entry_o
.
instruction
[
6
:
0
]
==
riscv
::
OpcodeAmo
));
assign
has_mem_access_o
=
(
|
nr_mem_n
)
|
(
|
input_is_mem
)
|
output_is_mem
;
always_comb
begin
nr_mem_n
=
nr_mem_q
;
for
(
int
unsigned
i
=
0
;
i
<
ariane_pkg
::
INSTR_PER_FETCH
;
i
++
)
begin
if
(
push_instr_fifo
[
i
])
begin
nr_mem_n
=
nr_mem_n
+
1'b1
;
end
end
if
(
fetch_entry_ready_i
)
begin
nr_mem_n
=
nr_mem_n
-
1'b1
;
end
end
assign
has_mem_access_o
=
(
|
fifo_instr_is_mem
)
|
(
|
input_is_mem
)
|
output_is_mem
;
always_comb
begin
idx_ds_d
=
idx_ds_q
;
...
...
@@ -318,7 +317,7 @@ module instr_queue (
for
(
genvar
i
=
0
;
i
<
ariane_pkg
::
INSTR_PER_FETCH
;
i
++
)
begin
:
gen_instr_fifo
// Make sure we don't save any instructions if we couldn't save the address
assign
push_instr_fifo
[
i
]
=
push_instr
[
i
]
&
~
address_overflow
;
fifo
_v3
#(
instr_
fifo
#(
.
DEPTH
(
ariane_pkg
::
FETCH_FIFO_DEPTH
),
.
dtype
(
instr_data_t
)
)
i_fifo_instr_data
(
...
...
@@ -332,7 +331,9 @@ module instr_queue (
.
data_i
(
instr_data_in
[
i
]
),
.
push_i
(
push_instr_fifo
[
i
]
),
.
data_o
(
instr_data_out
[
i
]
),
.
pop_i
(
pop_instr
[
i
]
)
.
pop_i
(
pop_instr
[
i
]
),
.
full_data_o
(
fifo_instr
[
i
]),
.
full_data_valid_o
(
fifo_instr_valid
[
i
])
);
end
// or reduce and check whether we are retiring a taken branch (might be that the corresponding)
...
...
@@ -374,7 +375,6 @@ module instr_queue (
idx_is_q
<=
'0
;
pc_q
<=
'0
;
reset_address_q
<=
1'b1
;
nr_mem_q
<=
'0
;
end
else
begin
pc_q
<=
pc_d
;
reset_address_q
<=
reset_address_d
;
...
...
@@ -384,11 +384,9 @@ module instr_queue (
// binary encoded
idx_is_q
<=
'0
;
reset_address_q
<=
1'b1
;
nr_mem_q
<=
'0
;
end
else
begin
idx_ds_q
<=
idx_ds_d
;
idx_is_q
<=
idx_is_d
;
nr_mem_q
<=
nr_mem_n
;
end
end
end
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment