mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-23 05:27:30 -04:00
Merge branch 'master' of iis-git.ee.ethz.ch:pulp-project/riscv
This commit is contained in:
commit
9ecd6d9868
16 changed files with 1249 additions and 116 deletions
22
README.md
Normal file
22
README.md
Normal file
|
@ -0,0 +1,22 @@
|
|||
# RI5CY: RISC-V Core
|
||||
|
||||
RI5CY is a small 4-stage RISC-V core. It starte its life as a
|
||||
fork of the OR10N cpu core that is based on the OpenRISC ISA.
|
||||
|
||||
RI5CY fully implements the RV32I instruction set, the multiply instruction from
|
||||
RV32M and many custom instruction set extensions that improve its performance
|
||||
for signal processing applications.
|
||||
|
||||
The core was developed as part of the [PULP platform](http://pulp.ethz.ch/) for
|
||||
energy-efficient computing and is currently used as the processing core for
|
||||
PULP and PULPino.
|
||||
|
||||
## Documentation
|
||||
|
||||
A datasheet that explains the most important features of the core can be found
|
||||
in `docs/datasheet/`.
|
||||
|
||||
It is written using LaTeX and can be generated as follows
|
||||
|
||||
make all
|
||||
|
|
@ -71,7 +71,8 @@ module riscv_controller
|
|||
|
||||
input logic trap_hit_i, // a trap was hit, so we have to flush EX and WB
|
||||
|
||||
output logic save_pc_id_o,
|
||||
output logic exc_save_id_o,
|
||||
output logic exc_restore_id_o,
|
||||
|
||||
// Debug Unit Signals
|
||||
input logic dbg_stall_i, // Pipeline stall is requested
|
||||
|
@ -158,23 +159,24 @@ module riscv_controller
|
|||
always_comb
|
||||
begin
|
||||
// Default values
|
||||
instr_req_o = 1'b1;
|
||||
instr_req_o = 1'b1;
|
||||
|
||||
exc_ack_o = 1'b0;
|
||||
save_pc_id_o = 1'b0;
|
||||
exc_ack_o = 1'b0;
|
||||
exc_save_id_o = 1'b0;
|
||||
exc_restore_id_o = 1'b0;
|
||||
|
||||
pc_mux_o = `PC_BOOT;
|
||||
pc_set_o = 1'b0;
|
||||
jump_done = jump_done_q;
|
||||
pc_mux_o = `PC_BOOT;
|
||||
pc_set_o = 1'b0;
|
||||
jump_done = jump_done_q;
|
||||
|
||||
ctrl_fsm_ns = ctrl_fsm_cs;
|
||||
ctrl_fsm_ns = ctrl_fsm_cs;
|
||||
|
||||
core_busy_o = 1'b1;
|
||||
is_decoding_o = 1'b0;
|
||||
core_busy_o = 1'b1;
|
||||
is_decoding_o = 1'b0;
|
||||
|
||||
halt_if_o = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
dbg_trap_o = 1'b0;
|
||||
halt_if_o = 1'b0;
|
||||
halt_id_o = 1'b0;
|
||||
dbg_trap_o = 1'b0;
|
||||
|
||||
unique case (ctrl_fsm_cs)
|
||||
// We were just reset, wait for fetch_enable
|
||||
|
@ -227,7 +229,7 @@ module riscv_controller
|
|||
|
||||
// TODO: This assumes that the pipeline is always flushed before
|
||||
// going to sleep.
|
||||
save_pc_id_o = 1'b1;
|
||||
exc_save_id_o = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -266,7 +268,7 @@ module riscv_controller
|
|||
exc_ack_o = 1'b1;
|
||||
|
||||
halt_id_o = 1'b1; // we don't want to propagate this instruction to EX
|
||||
save_pc_id_o = 1'b1;
|
||||
exc_save_id_o = 1'b1;
|
||||
|
||||
// we don't have to change our current state here as the prefetch
|
||||
// buffer is automatically invalidated, thus the next instruction
|
||||
|
@ -276,8 +278,9 @@ module riscv_controller
|
|||
end
|
||||
|
||||
if (eret_insn_i) begin
|
||||
pc_mux_o = `PC_ERET;
|
||||
pc_set_o = 1'b1;
|
||||
pc_mux_o = `PC_ERET;
|
||||
pc_set_o = 1'b1;
|
||||
exc_restore_id_o = 1'b1;
|
||||
end
|
||||
|
||||
// handle WFI instruction, flush pipeline and (potentially) go to
|
||||
|
|
|
@ -55,10 +55,11 @@ module riscv_cs_registers
|
|||
|
||||
// Interrupts
|
||||
output logic irq_enable_o,
|
||||
output logic [31:0] epcr_o,
|
||||
output logic [31:0] mepc_o,
|
||||
|
||||
input logic [31:0] curr_pc_id_i,
|
||||
input logic save_pc_id_i,
|
||||
input logic exc_save_i,
|
||||
input logic exc_restore_i,
|
||||
|
||||
input logic [5:0] exc_cause_i,
|
||||
input logic save_exc_cause_i,
|
||||
|
@ -115,17 +116,16 @@ module riscv_cs_registers
|
|||
logic is_pcer;
|
||||
logic is_pcmr;
|
||||
|
||||
// Generic CSRs
|
||||
logic [31:0] mepc_q, mepc_n;
|
||||
|
||||
// CSR update logic
|
||||
logic [31:0] csr_wdata_int;
|
||||
logic [31:0] csr_rdata_int;
|
||||
logic csr_we_int;
|
||||
|
||||
// Interrupt control signals
|
||||
logic irq_enable, irq_enable_n;
|
||||
logic [5:0] exc_cause, exc_cause_n;
|
||||
logic [31:0] mepc_q, mepc_n;
|
||||
logic [ 0:0] mestatus_q, mestatus_n;
|
||||
logic [ 0:0] mstatus_q, mstatus_n;
|
||||
logic [ 5:0] exc_cause, exc_cause_n;
|
||||
|
||||
|
||||
////////////////////////////////////////////
|
||||
|
@ -144,7 +144,7 @@ module riscv_cs_registers
|
|||
|
||||
case (csr_addr_i)
|
||||
// mstatus: always M-mode, contains IE bit
|
||||
12'h300: csr_rdata_int = {29'b0, 2'b11, irq_enable};
|
||||
12'h300: csr_rdata_int = {29'b0, 2'b11, mstatus_q};
|
||||
|
||||
// mepc: exception program counter
|
||||
12'h341: csr_rdata_int = mepc_q;
|
||||
|
@ -165,6 +165,8 @@ module riscv_cs_registers
|
|||
12'h7B4: csr_rdata_int = hwlp_start_i[1];
|
||||
12'h7B5: csr_rdata_int = hwlp_end_i[1];
|
||||
12'h7B6: csr_rdata_int = hwlp_cnt_i[1];
|
||||
|
||||
12'h7C0: csr_rdata_int = {29'b0, 2'b11, mestatus_q};
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -173,14 +175,15 @@ module riscv_cs_registers
|
|||
always_comb
|
||||
begin
|
||||
mepc_n = mepc_q;
|
||||
irq_enable_n = irq_enable;
|
||||
mestatus_n = mestatus_q;
|
||||
mstatus_n = mstatus_q;
|
||||
exc_cause_n = exc_cause;
|
||||
hwlp_we_o = '0;
|
||||
hwlp_regid_o = '0;
|
||||
|
||||
case (csr_addr_i)
|
||||
// mstatus: IE bit
|
||||
12'h300: if (csr_we_int) irq_enable_n = csr_wdata_int[0];
|
||||
12'h300: if (csr_we_int) mstatus_n = csr_wdata_int[0];
|
||||
|
||||
// mepc: exception program counter
|
||||
12'h341: if (csr_we_int) mepc_n = csr_wdata_int;
|
||||
|
@ -194,7 +197,24 @@ module riscv_cs_registers
|
|||
12'h7B4: if (csr_we_int) begin hwlp_we_o = 3'b001; hwlp_regid_o = 1'b1; end
|
||||
12'h7B5: if (csr_we_int) begin hwlp_we_o = 3'b010; hwlp_regid_o = 1'b1; end
|
||||
12'h7B6: if (csr_we_int) begin hwlp_we_o = 3'b100; hwlp_regid_o = 1'b1; end
|
||||
|
||||
// mestatus: machine exception status
|
||||
12'h7C0: if (csr_we_int) mestatus_n = csr_wdata_int[0];
|
||||
endcase
|
||||
|
||||
// exception controller gets priority over other writes
|
||||
if (exc_save_i) begin
|
||||
mepc_n = curr_pc_id_i;
|
||||
mestatus_n = mstatus_q;
|
||||
mstatus_n = 1'b0;
|
||||
end
|
||||
|
||||
if (save_exc_cause_i)
|
||||
exc_cause_n = exc_cause_i;
|
||||
|
||||
if (exc_restore_i) begin
|
||||
mstatus_n = mestatus_q;
|
||||
end
|
||||
end
|
||||
|
||||
assign hwlp_data_o = csr_wdata_int;
|
||||
|
@ -231,8 +251,8 @@ module riscv_cs_registers
|
|||
|
||||
|
||||
// directly output some registers
|
||||
assign irq_enable_o = irq_enable;
|
||||
assign epcr_o = mepc_q;
|
||||
assign irq_enable_o = mstatus_q[0];
|
||||
assign mepc_o = mepc_q;
|
||||
|
||||
|
||||
// actual registers
|
||||
|
@ -240,25 +260,20 @@ module riscv_cs_registers
|
|||
begin
|
||||
if (rst_n == 1'b0)
|
||||
begin
|
||||
irq_enable <= 1'b0;
|
||||
mstatus_q <= '0;
|
||||
mepc_q <= '0;
|
||||
mestatus_q <= '0;
|
||||
exc_cause <= '0;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// update CSRs
|
||||
irq_enable <= irq_enable_n;
|
||||
mstatus_q <= mstatus_n;
|
||||
|
||||
// exception controller gets priority over other writes
|
||||
if (save_pc_id_i == 1'b1)
|
||||
mepc_q <= curr_pc_id_i;
|
||||
else
|
||||
mepc_q <= mepc_n;
|
||||
mepc_q <= mepc_n;
|
||||
mestatus_q <= mestatus_n;
|
||||
|
||||
if (save_exc_cause_i)
|
||||
exc_cause <= exc_cause_i;
|
||||
else
|
||||
exc_cause <= exc_cause_n;
|
||||
exc_cause <= exc_cause_n;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -18,9 +18,10 @@ as possible and avoid any overhead that we do not explicitely need.
|
|||
00 & 11 & 01 & 000001 & 0x341 & MEPC & R/W & Machine exception program counter \\ \hline
|
||||
00 & 11 & 01 & 000010 & 0x342 & MCAUSE & R/W & Machine trap cause \\ \hline
|
||||
01 & 11 & 00 & 0XXXXX & 0x780 - 0x79F & PCCRs & R/W & Performance Counter Counter Registers \\ \hline
|
||||
01 & 11 & 10 & 200000 & 0x7A0 & PCER & R/W & Performance Counter Enable Register \\ \hline
|
||||
01 & 11 & 10 & 100000 & 0x7A0 & PCER & R/W & Performance Counter Enable Register \\ \hline
|
||||
01 & 11 & 10 & 100001 & 0x7A1 & PCMR & R/W & Performance Counter Mode Register \\ \hline
|
||||
01 & 11 & 10 & 110XXX & 0x7B0 - 0x7B6 & HWLP & R/W & Hardware Loop Registers \\ \hline
|
||||
01 & 11 & 10 & 111000 & 0x7C0 & MESTATUS & R/W & Machine exception Status Register \\ \hline
|
||||
11 & 11 & 00 & 000000 & 0xF00 & MCPUID & R & CPU description \\ \hline
|
||||
11 & 11 & 00 & 000001 & 0xF01 & MIMPID & R & Vendor ID and version number \\ \hline
|
||||
11 & 11 & 00 & 010000 & 0xF10 & MHARTID & R & Hardware Thread ID \\ \bottomrule
|
||||
|
@ -41,6 +42,28 @@ as possible and avoid any overhead that we do not explicitely need.
|
|||
}
|
||||
|
||||
Note that \signal{PRV[1:0]} is statically \signal{2'b11} and cannot be altered (read-only).
|
||||
When en exception is encountered, \signal{Interrupt Enable} will be set to
|
||||
\signal{1'b0}. When the \signal{eret} instruction is executed, the original
|
||||
value of \signal{Interrupt Enable} will be restored, as \signal{MESTATUS} will
|
||||
replace \signal{MSTATUS}.
|
||||
If you want to enable interrupt handling in your exception hanlder, set the
|
||||
\signal{Interrupt Enable} to \signal{1'b1} inside your handler code.
|
||||
|
||||
\subsection{MESTATUS}
|
||||
\csrDesc{0x7C0}{0x0000\_0006}{MESTATUS}{
|
||||
\begin{bytefield}[endianness=big,bitheight=60pt]{32}
|
||||
\bitheader{31,2,1,0} \\
|
||||
\bitbox{29}{ Unused }
|
||||
\bitbox{2}{\rotatebox{90}{\tiny PRV[1:0] }}
|
||||
\bitbox{1}{\rotatebox{90}{\tiny Interrupt Enable }}
|
||||
\end{bytefield}
|
||||
}
|
||||
|
||||
Note that \signal{PRV[1:0]} is statically \signal{2'b11} and cannot be altered (read-only).
|
||||
|
||||
When an exception is encountered, the current value of \signal{MSTATUS} is saved
|
||||
in \signal{MESTATUS}. When an \instr{eret} instruction is executed, the value
|
||||
from \signal{MESTATUS} replaces the \signal{MSTATUS} register.
|
||||
|
||||
|
||||
\subsection{MEPC}
|
||||
|
@ -52,9 +75,9 @@ Note that \signal{PRV[1:0]} is statically \signal{2'b11} and cannot be altered (
|
|||
}
|
||||
|
||||
When an exception is encountered, the current program counter is saved in
|
||||
\signal{mepc} and the core jumps to the exception address.
|
||||
When an \instr{eret} instruction is executed, the value from \signal{mepc}
|
||||
replaces the current program counter.
|
||||
\signal{MEPC}, and the core jumps to the exception address. When an \instr{eret}
|
||||
instruction is executed, the value from \signal{MEPC} replaces the current
|
||||
program counter.
|
||||
|
||||
\subsection{MCAUSE}
|
||||
\csrDesc{0x341}{0x0000\_0000}{MCAUSE}{
|
||||
|
|
|
@ -29,7 +29,15 @@ exception/interrupt.
|
|||
interrupt lines. Interrupts can only be enabled/disabled on a global basis and
|
||||
not individually. It is assumed that there is an event/interrupt controller
|
||||
outside of the core that performs masking and buffering of the interrupt lines.
|
||||
The global interrupt enable is done via the CSR register \signal{mstatus}.
|
||||
The global interrupt enable is done via the CSR register \signal{MSTATUS}.
|
||||
|
||||
If multiple interrupts arrive in the same cycle, the interrupt with the lowest
|
||||
number will be executed first. As soon as IRQs are re-enabled, either after an
|
||||
\signal{eret} or an explicit enable, the interrupt with lowest number will be
|
||||
executed.
|
||||
This means that it is important to clear the interrupt line before re-enabling
|
||||
interrupts, as otherwise the same interrupt handler could be called over and
|
||||
over again.
|
||||
|
||||
\section{Exceptions}
|
||||
|
||||
|
@ -38,16 +46,21 @@ exceptions and ecall instruction exceptions can not be disabled and are always
|
|||
active.
|
||||
|
||||
The illegal instruction exception and the load and store invalid memory access
|
||||
exceptions are precise exceptions, i.e. the value of \signal{mepc} will be the
|
||||
exceptions are precise exceptions, i.e. the value of \signal{MEPC} will be the
|
||||
instruction address that caused it.
|
||||
|
||||
\section{Handling}
|
||||
|
||||
\rvcore does not support nested interrupt/exception handling. Exceptions inside
|
||||
interrupt/exception handlers are ignored and thus a user must ensure that such
|
||||
a situation does not happen, as otherwise the behaviour is undefined.
|
||||
\rvcore does support nested interrupt/exception handling. Exceptions inside
|
||||
interrupt/exception handlers cause another exception, thus exceptions during the
|
||||
critical part of your exception handlers, i.e. before having saved the
|
||||
\signal{MEPC} and \signal{MESTATUS} registers, will cause those register to be
|
||||
overwritten.
|
||||
Interrupts during interrupt/exception handlers are disabled by default, but can
|
||||
be explicitely enabled if desired.
|
||||
|
||||
Upon executing an \instr{eret} instruction, the core jumps to the program
|
||||
counter saved in the CSR register \signal{mepc}. When entering an
|
||||
interrupt/exception handler, the core sets \signal{mepc} to the current program
|
||||
counter.
|
||||
counter saved in the CSR register \signal{MEPC} and restores the value of
|
||||
register \signal{MESTATUS} to \signal{MSTATUS}. When entering an
|
||||
interrupt/exception handler, the core sets \signal{MEPC} to the current program
|
||||
counter and saves the current value of \signal{MSTATUS} in \signal{MESTATUS}.
|
||||
|
|
|
@ -13,6 +13,9 @@ the loop body is executed. RI5CY contains two hardware loop register sets, each
|
|||
of them can store these three values.
|
||||
If the end address of the two hardware loops is identical, loop 0 has higher
|
||||
priority and only the loop counter for hardware loop 0 is decremented.
|
||||
As soon as the counter of loop 0 reaches 1 at an end address, meaning it is
|
||||
decremented to 0 now, loop 1 gets active too. In this case, both counters will
|
||||
be decremented and the core jumps to the start of loop 1.
|
||||
|
||||
The instructions described below are used to setup the hardware loop registers.
|
||||
Note that the minimum loop size is two instructions.
|
||||
|
|
44
docs/datasheet/content/pipeline.tex
Normal file
44
docs/datasheet/content/pipeline.tex
Normal file
|
@ -0,0 +1,44 @@
|
|||
\chapter{Pipeline}
|
||||
\label{chap:pipeline}
|
||||
|
||||
\rvcore has a fully independent pipeline, meaning that whenever possible data
|
||||
will propagate through the pipeline and therefor does not suffer from any
|
||||
unneeded stalls.
|
||||
|
||||
The pipeline design is easily extendable to incorporate out-of-order
|
||||
completion. E.g. it would be possible to complete an instruction that only
|
||||
needs the EX stage before the WB stage, that is currently blocked waiting for
|
||||
an rvalid, is ready.
|
||||
Currently this is not done in \rvcore, but might be added in the future.
|
||||
|
||||
Figure~\ref{fig:pipeline} shows the control signals relevant for the pipeline
|
||||
operation. Running from right to left are the main control signals, the
|
||||
\signal{ready} signals of each pipeline stage.
|
||||
Each pipeline stage has two control inputs: an enable and a clear. The enable
|
||||
activates the pipeline stage and the core moves forward by one instruction. The
|
||||
clear removes the instruction from the pipeline stage as it is completed.
|
||||
At every pipeline stage, when the \signal{ready} coming from the stage to the
|
||||
right is high, but the valid signal of the stage is low, the stage is cleared.
|
||||
If the valid signal is high, it is enabled.
|
||||
|
||||
Going from right to left every stage is independent, no stage depends on the
|
||||
stage on its left. Going from left to right every stage depends on its right
|
||||
neighbor and can only continue when it is ready.
|
||||
This means that in addition that a single stage has to be ready, also the stage
|
||||
on its right has to be ready to move on.
|
||||
|
||||
\begin{figure}[H]
|
||||
\centering
|
||||
\includegraphics[width=0.9\textwidth]{./figures/pipeline}
|
||||
\caption{\rvcore Pipeline.}
|
||||
\label{fig:pipeline}
|
||||
\end{figure}
|
||||
|
||||
|
||||
|
||||
\begin{boxnote}
|
||||
In contrast to \orion there is no global stall controller any more, instead
|
||||
every stage manages its own dependencies. The main controller of \rvcore is now
|
||||
only responsible for control flow operations, i.e. flushing the pipe, branches,
|
||||
jumps and exceptions.
|
||||
\end{boxnote}
|
|
@ -37,6 +37,7 @@
|
|||
\input{./content/mac.tex}
|
||||
\input{./content/aluext.tex}
|
||||
\input{./content/hwloop.tex}
|
||||
\input{./content/pipeline.tex}
|
||||
\input{./content/rf.tex}
|
||||
\input{./content/csr.tex}
|
||||
\input{./content/perfcounters.tex}
|
||||
|
|
641
docs/datasheet/figures_raw/pipeline.obj
Normal file
641
docs/datasheet/figures_raw/pipeline.obj
Normal file
|
@ -0,0 +1,641 @@
|
|||
%TGIF 4.2.5-QPL
|
||||
state(0,37,100.000,0,0,0,32,1,16,2,2,1,0,0,0,1,1,'Helvetica-Bold',1,97920,0,0,0,10,0,0,1,1,0,16,0,0,1,1,1,1,1088,1408,1,0,5760,0).
|
||||
%
|
||||
% @(#)$Header$
|
||||
% %W%
|
||||
%
|
||||
unit("1 pixel/pixel").
|
||||
color_info(66,65535,0,[
|
||||
"black", 0, 0, 0, 0, 0, 0, 1,
|
||||
"white", 65535, 65535, 65535, 65535, 65535, 65535, 1,
|
||||
"#F0F0F0", 61680, 61680, 61680, 61440, 61440, 61440, 1,
|
||||
"#C8C8C8", 51400, 51400, 51400, 51200, 51200, 51200, 1,
|
||||
"#505050", 20560, 20560, 20560, 20480, 20480, 20480, 1,
|
||||
"#282828", 10280, 10280, 10280, 10240, 10240, 10240, 1,
|
||||
"#FF0000", 65535, 0, 0, 65280, 0, 0, 1,
|
||||
"#0000FF", 0, 0, 65535, 0, 0, 65280, 1,
|
||||
"#00FF00", 0, 65535, 0, 0, 65280, 0, 1,
|
||||
"#009000", 0, 37008, 0, 0, 36864, 0, 1,
|
||||
"#1F407A", 7967, 16448, 31354, 7936, 16384, 31232, 1,
|
||||
"#3C5A0F", 15420, 23130, 3855, 15360, 23040, 3840, 1,
|
||||
"#0069B4", 0, 26985, 46260, 0, 26880, 46080, 1,
|
||||
"#71791C", 29041, 31097, 7196, 28928, 30976, 7168, 1,
|
||||
"#91056A", 37265, 1285, 27242, 37120, 1280, 27136, 1,
|
||||
"#6F6F6E", 28527, 28527, 28270, 28416, 28416, 28160, 1,
|
||||
"#A8322D", 43176, 12850, 11565, 43008, 12800, 11520, 1,
|
||||
"#007A92", 0, 31354, 37522, 0, 31232, 37376, 1,
|
||||
"#956013", 38293, 24672, 4883, 38144, 24576, 4864, 1,
|
||||
"#82BE1E", 33410, 48830, 7710, 33280, 48640, 7680, 1,
|
||||
"#758fbd", 30069, 36751, 48573, 29952, 36608, 48384, 1,
|
||||
"#8eab63", 36494, 43947, 25443, 36352, 43776, 25344, 1,
|
||||
"#6cacd9", 27756, 44204, 55769, 27648, 44032, 55552, 1,
|
||||
"#b4ba72", 46260, 47802, 29298, 46080, 47616, 29184, 1,
|
||||
"#c967ae", 51657, 26471, 44718, 51456, 26368, 44544, 1,
|
||||
"#b8b8b6", 47288, 47288, 46774, 47104, 47104, 46592, 1,
|
||||
"#d48985", 54484, 35209, 34181, 54272, 35072, 34048, 1,
|
||||
"#65b9c9", 25957, 47545, 51657, 25856, 47360, 51456, 1,
|
||||
"#c9a571", 51657, 42405, 29041, 51456, 42240, 28928, 1,
|
||||
"#bbde81", 48059, 57054, 33153, 47872, 56832, 33024, 1,
|
||||
"#a5b7d6", 42405, 47031, 54998, 42240, 46848, 54784, 1,
|
||||
"#b8cc99", 47288, 52428, 39321, 47104, 52224, 39168, 1,
|
||||
"#a2cbe8", 41634, 52171, 59624, 41472, 51968, 59392, 1,
|
||||
"#d2d6a5", 53970, 54998, 42405, 53760, 54784, 42240, 1,
|
||||
"#de9ecc", 57054, 40606, 52428, 56832, 40448, 52224, 1,
|
||||
"#d4d4d2", 54484, 54484, 53970, 54272, 54272, 53760, 1,
|
||||
"#e6b5b3", 59110, 46517, 46003, 58880, 46336, 45824, 1,
|
||||
"#9bd3de", 39835, 54227, 57054, 39680, 54016, 56832, 1,
|
||||
"#dec6a4", 57054, 50886, 42148, 56832, 50688, 41984, 1,
|
||||
"#d5ebb0", 54741, 60395, 45232, 54528, 60160, 45056, 1,
|
||||
"#b3cde3", 46003, 52685, 58339, 45824, 52480, 58112, 1,
|
||||
"#bae4bc", 47802, 58596, 48316, 47616, 58368, 48128, 1,
|
||||
"#edf8fb", 60909, 63736, 64507, 60672, 63488, 64256, 1,
|
||||
"#ffffcc", 65535, 65535, 52428, 65280, 65280, 52224, 1,
|
||||
"magenta", 65535, 0, 65535, 65535, 0, 65535, 1,
|
||||
"#f0f9e8", 61680, 63993, 59624, 61440, 63744, 59392, 1,
|
||||
"#feebe2", 65278, 60395, 58082, 65024, 60160, 57856, 1,
|
||||
"cyan", 0, 65535, 65535, 0, 65535, 65535, 1,
|
||||
"#fecc5c", 65278, 52428, 23644, 65024, 52224, 23552, 1,
|
||||
"yellow", 65535, 65535, 0, 65535, 65535, 0, 1,
|
||||
"red", 65535, 0, 0, 65535, 0, 0, 1,
|
||||
"green", 0, 65535, 0, 0, 65535, 0, 1,
|
||||
"blue", 0, 0, 65535, 0, 0, 65535, 1,
|
||||
"pink", 65535, 49344, 52171, 65535, 49344, 52171, 1,
|
||||
"CadetBlue", 24415, 40606, 41120, 24415, 40606, 41120, 1,
|
||||
"DarkSlateGray", 12079, 20303, 20303, 12079, 20303, 20303, 1,
|
||||
"#FF4D08", 65535, 19789, 2056, 65280, 19712, 2048, 1,
|
||||
"#FF6437", 65535, 25700, 14135, 65280, 25600, 14080, 1,
|
||||
"#7F321B", 32639, 12850, 6939, 32512, 12800, 6912, 1,
|
||||
"#FF8080", 65535, 32896, 32896, 65280, 32768, 32768, 1,
|
||||
"#FF8A7E", 65535, 35466, 32382, 65280, 35328, 32256, 1,
|
||||
"#FFC37C", 65535, 50115, 31868, 65280, 49920, 31744, 1,
|
||||
"#7F4A0D", 32639, 19018, 3341, 32512, 18944, 3328, 1,
|
||||
"#DE82FF", 57054, 33410, 65535, 56832, 33280, 65280, 1,
|
||||
"#EFB8FF", 61423, 47288, 65535, 61184, 47104, 65280, 1,
|
||||
"#6F367F", 28527, 13878, 32639, 28416, 13824, 32512, 1
|
||||
]).
|
||||
script_frac("0.6").
|
||||
fg_bg_colors('#A8322D','white').
|
||||
dont_reencode("FFDingbests:ZapfDingbats").
|
||||
objshadow_info('#c0c0c0',2,2).
|
||||
rotate_pivot(0,0,0,0).
|
||||
spline_tightness(1).
|
||||
page(1,"",1,'').
|
||||
box('#EFB8FF','',288,256,320,560,1,2,0,288070,0,0,0,0,0,'2',0,[
|
||||
]).
|
||||
box('#EFB8FF','',592,256,624,560,1,2,0,288062,0,0,0,0,0,'2',0,[
|
||||
]).
|
||||
box('#EFB8FF','',888,400,920,560,1,2,0,288031,0,0,0,0,0,'2',0,[
|
||||
]).
|
||||
rcbox('#f0f9e8','',332,256,580,616,1,1,0,0,16,287695,0,0,0,0,'1',0,[
|
||||
]).
|
||||
rcbox('#f0f9e8','',636,256,876,616,1,1,0,0,16,287722,0,0,0,0,'1',0,[
|
||||
]).
|
||||
rcbox('#f0f9e8','',932,256,1052,616,1,1,0,0,16,287742,0,0,0,0,'1',0,[
|
||||
]).
|
||||
rcbox('#f0f9e8','',24,256,276,616,1,1,0,0,16,287635,0,0,0,0,'1',0,[
|
||||
]).
|
||||
rcbox('#d4d4d2','',24,256,276,616,0,1,1,0,16,287685,0,0,0,0,'1',0,[
|
||||
]).
|
||||
poly('black','',2,[
|
||||
820,280,820,192],1,1,1,286345,0,0,0,0,0,0,0,'1',0,0,
|
||||
"0","",[
|
||||
0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[
|
||||
]).
|
||||
text('black',816,170,1,1,1,40,17,286346,14,3,0,0,0,0,2,40,17,0,0,"",0,0,0,0,184,'',[
|
||||
minilines(40,17,0,0,1,0,0,[
|
||||
mini_line(40,14,3,0,0,0,[
|
||||
str_block(0,40,14,3,0,-1,0,0,0,[
|
||||
str_seg('#0069B4','Courier-Bold',1,97920,40,14,3,0,-1,0,0,0,0,0,
|
||||
"addr")])
|
||||
])
|
||||
])]).
|
||||
text('black',960,170,1,1,1,60,17,286404,14,3,0,0,0,0,2,60,17,0,0,"",0,0,0,0,184,'',[
|
||||
minilines(60,17,0,0,1,0,0,[
|
||||
mini_line(60,14,3,0,0,0,[
|
||||
str_block(0,60,14,3,0,-1,0,0,0,[
|
||||
str_seg('#0069B4','Courier-Bold',1,97920,60,14,3,0,-1,0,0,0,0,0,
|
||||
"rvalid")])
|
||||
])
|
||||
])]).
|
||||
text('black',872,170,1,1,1,50,17,286468,14,3,0,0,0,0,2,50,17,0,0,"",0,0,0,0,184,'',[
|
||||
minilines(50,17,0,0,1,0,0,[
|
||||
mini_line(50,14,3,0,0,0,[
|
||||
str_block(0,50,14,3,0,-1,0,0,0,[
|
||||
str_seg('#0069B4','Courier-Bold',1,97920,50,14,3,0,-1,0,0,0,0,0,
|
||||
"grant")])
|
||||
])
|
||||
])]).
|
||||
rcbox('#0069B4','',784,136,1024,192,0,1,1,0,16,286710,0,0,0,0,'1',0,[
|
||||
]).
|
||||
text('black',888,142,1,1,1,127,23,286718,18,5,0,0,0,0,2,127,23,0,0,"",0,0,0,0,160,'',[
|
||||
minilines(127,23,0,0,1,0,0,[
|
||||
mini_line(127,18,5,0,0,0,[
|
||||
str_block(0,127,18,5,0,-1,0,0,0,[
|
||||
str_seg('#0069B4','Helvetica-Bold',1,115200,127,18,5,0,-1,0,0,0,0,0,
|
||||
"Data Interface")])
|
||||
])
|
||||
])]).
|
||||
box('black','',12,224,1064,664,0,1,1,286736,0,0,0,0,0,'1',0,[
|
||||
]).
|
||||
text('black',184,170,1,1,1,40,17,286355,14,3,0,0,0,0,2,40,17,0,0,"",0,0,0,0,184,'',[
|
||||
minilines(40,17,0,0,1,0,0,[
|
||||
mini_line(40,14,3,0,0,0,[
|
||||
str_block(0,40,14,3,0,-1,0,0,0,[
|
||||
str_seg('#0069B4','Courier-Bold',1,97920,40,14,3,0,-1,0,0,0,0,0,
|
||||
"addr")])
|
||||
])
|
||||
])]).
|
||||
text('black',120,170,1,1,1,60,17,286569,14,3,0,0,0,0,2,60,17,0,0,"",0,0,0,0,184,'',[
|
||||
minilines(60,17,0,0,1,0,0,[
|
||||
mini_line(60,14,3,0,0,0,[
|
||||
str_block(0,60,14,3,0,-1,0,0,0,[
|
||||
str_seg('#0069B4','Courier-Bold',1,97920,60,14,3,0,-1,0,0,0,0,0,
|
||||
"rvalid")])
|
||||
])
|
||||
])]).
|
||||
rcbox('#0069B4','',56,136,264,192,0,1,1,0,16,286711,0,0,0,0,'1',0,[
|
||||
]).
|
||||
text('black',160,142,1,1,1,181,23,286715,18,5,0,0,0,0,2,181,23,0,0,"",0,0,0,0,160,'',[
|
||||
minilines(181,23,0,0,1,0,0,[
|
||||
mini_line(181,18,5,0,0,0,[
|
||||
str_block(0,181,18,5,0,-1,0,0,0,[
|
||||
str_seg('#0069B4','Helvetica-Bold',1,115200,181,18,5,0,-1,0,0,0,0,0,
|
||||
"Instruction Interface")])
|
||||
])
|
||||
])]).
|
||||
box('#6F367F','',288,256,320,560,0,2,1,283037,0,0,0,0,0,'2',0,[
|
||||
]).
|
||||
text('black',294,415,2,0,1,20,35,283038,14,3,0,0,0,0,2,20,34,0,0,"",0,1,0,0,429,'',[
|
||||
294,415,294,415,314,449,1000,0,0,1022.73,0,4,293,414,315,450],[
|
||||
minilines(20,34,0,0,0,0,0,[
|
||||
mini_line(20,14,3,0,0,0,[
|
||||
str_block(0,20,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,20,14,3,0,-1,0,0,0,0,0,
|
||||
"IF")])
|
||||
]),
|
||||
mini_line(20,14,3,0,0,0,[
|
||||
str_block(0,20,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,20,14,3,0,-1,0,0,0,0,0,
|
||||
"ID")])
|
||||
])
|
||||
])]).
|
||||
box('#6F367F','',592,256,624,560,0,2,1,283031,0,0,0,0,0,'2',0,[
|
||||
]).
|
||||
text('black',598,415,2,0,1,20,34,283032,14,3,0,0,0,0,2,20,34,0,0,"",0,0,0,0,429,'',[
|
||||
minilines(20,34,0,0,0,0,0,[
|
||||
mini_line(20,14,3,0,0,0,[
|
||||
str_block(0,20,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,20,14,3,0,-1,0,0,0,0,0,
|
||||
"ID")])
|
||||
]),
|
||||
mini_line(20,14,3,0,0,0,[
|
||||
str_block(0,20,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,20,14,3,0,0,0,0,0,0,0,
|
||||
"EX")])
|
||||
])
|
||||
])]).
|
||||
box('#6F367F','',888,400,920,560,0,2,1,283042,0,0,0,0,0,'2',0,[
|
||||
]).
|
||||
text('black',894,415,2,0,1,20,34,283043,14,3,0,0,0,0,2,20,34,0,0,"",0,0,0,0,429,'',[
|
||||
minilines(20,34,0,0,0,0,0,[
|
||||
mini_line(20,14,3,0,0,0,[
|
||||
str_block(0,20,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,20,14,3,0,0,0,0,0,0,0,
|
||||
"EX")])
|
||||
]),
|
||||
mini_line(20,14,3,0,0,0,[
|
||||
str_block(0,20,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,20,14,3,0,-1,0,0,0,0,0,
|
||||
"WB")])
|
||||
])
|
||||
])]).
|
||||
poly('black','',2,[
|
||||
172,280,172,192],1,1,1,287533,0,0,0,0,0,0,0,'1',0,0,
|
||||
"0","",[
|
||||
0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[
|
||||
]).
|
||||
poly('black','',2,[
|
||||
116,192,116,280],1,1,1,287631,0,0,0,0,0,0,0,'1',0,0,
|
||||
"0","",[
|
||||
0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[
|
||||
]).
|
||||
rcbox('#d4d4d2','',332,256,580,616,0,1,1,0,16,287693,0,0,0,0,'1',0,[
|
||||
]).
|
||||
rcbox('#d4d4d2','',636,256,876,616,0,1,1,0,16,287738,0,0,0,0,'1',0,[
|
||||
]).
|
||||
rcbox('#d4d4d2','',932,256,1052,616,0,1,1,0,16,287749,0,0,0,0,'1',0,[
|
||||
]).
|
||||
poly('#6F367F','',3,[
|
||||
296,560,304,548,312,560],0,2,1,288021,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#6F367F','',3,[
|
||||
600,560,608,548,616,560],0,2,1,288025,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#6F367F','',3,[
|
||||
896,560,904,548,912,560],0,2,1,288028,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
text('#6F367F',376,554,1,1,1,80,17,288303,14,3,0,0,0,0,-65534,80,17,0,0,"",0,0,0,0,568,'',[
|
||||
minilines(80,17,0,0,1,0,0,[
|
||||
mini_line(80,14,3,0,0,0,[
|
||||
str_block(0,80,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,80,14,3,0,0,0,0,0,0,0,
|
||||
"id_ready")])
|
||||
])
|
||||
])]).
|
||||
text('#6F367F',680,554,1,1,1,80,17,288352,14,3,0,0,0,0,-65534,80,17,0,0,"",0,0,0,0,568,'',[
|
||||
minilines(80,17,0,0,1,0,0,[
|
||||
mini_line(80,14,3,0,0,0,[
|
||||
str_block(0,80,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,80,14,3,0,0,0,0,0,0,0,
|
||||
"ex_ready")])
|
||||
])
|
||||
])]).
|
||||
text('#6F367F',980,554,1,1,1,80,17,288361,14,3,0,0,0,0,-65534,80,17,0,0,"",0,0,0,0,568,'',[
|
||||
minilines(80,17,0,0,1,0,0,[
|
||||
mini_line(80,14,3,0,0,0,[
|
||||
str_block(0,80,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,80,14,3,0,0,0,0,0,0,0,
|
||||
"wb_ready")])
|
||||
])
|
||||
])]).
|
||||
poly('black','',3,[
|
||||
496,384,496,560,472,560],1,2,1,288369,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('black','',2,[
|
||||
728,576,472,576],1,2,1,288370,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
text('#6F367F',456,410,1,1,1,60,17,288372,14,3,0,0,0,0,-65534,60,17,0,0,"",0,0,0,0,424,'',[
|
||||
minilines(60,17,0,0,1,0,0,[
|
||||
mini_line(60,14,3,0,0,0,[
|
||||
str_block(0,60,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,60,14,3,0,-1,0,0,0,0,0,
|
||||
"!stall")])
|
||||
])
|
||||
])]).
|
||||
text('#6F367F',744,402,1,1,1,70,17,288380,14,3,0,0,0,0,-65534,70,17,0,0,"",0,0,0,0,416,'',[
|
||||
minilines(70,17,0,0,1,0,0,[
|
||||
mini_line(70,14,3,0,0,0,[
|
||||
str_block(0,70,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,70,14,3,0,-1,0,0,0,0,0,
|
||||
"granted")])
|
||||
])
|
||||
])]).
|
||||
text('#6F367F',988,402,1,1,1,60,17,288385,14,3,0,0,0,0,-65534,60,17,0,0,"",0,0,0,0,416,'',[
|
||||
minilines(60,17,0,0,1,0,0,[
|
||||
mini_line(60,14,3,0,0,0,[
|
||||
str_block(0,60,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,60,14,3,0,-1,0,0,0,0,0,
|
||||
"rvalid")])
|
||||
])
|
||||
])]).
|
||||
poly('black','',2,[
|
||||
1028,576,776,576],1,2,1,288388,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#3C5A0F','',3,[
|
||||
424,576,424,608,464,608],0,2,1,288395,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#3C5A0F','',4,[
|
||||
448,608,568,608,568,520,592,520],1,2,1,288396,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
text('#6F367F',520,586,1,1,1,80,17,288398,14,3,0,0,0,0,-65534,80,17,0,0,"",0,0,0,0,600,'',[
|
||||
minilines(80,17,0,0,1,0,0,[
|
||||
mini_line(80,14,3,0,0,0,[
|
||||
str_block(0,80,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,80,14,3,0,-1,0,0,0,0,0,
|
||||
"id_valid")])
|
||||
])
|
||||
])]).
|
||||
poly('#3C5A0F','',3,[
|
||||
728,576,728,608,752,608],0,2,1,288403,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#3C5A0F','',4,[
|
||||
736,608,864,608,864,520,888,520],1,2,1,288404,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
text('#6F367F',816,586,1,1,1,80,17,288405,14,3,0,0,0,0,-65534,80,17,0,0,"",0,0,0,0,600,'',[
|
||||
minilines(80,17,0,0,1,0,0,[
|
||||
mini_line(80,14,3,0,0,0,[
|
||||
str_block(0,80,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,80,14,3,0,-1,0,0,0,0,0,
|
||||
"ex_valid")])
|
||||
])
|
||||
])]).
|
||||
poly('#3C5A0F','',3,[
|
||||
40,568,40,608,168,608],0,2,1,288407,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#3C5A0F','',4,[
|
||||
160,608,256,608,256,520,288,520],1,2,1,288408,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
text('#6F367F',208,586,1,1,1,80,17,288409,14,3,0,0,0,0,-65534,80,17,0,0,"",0,0,0,0,600,'',[
|
||||
minilines(80,17,0,0,1,0,0,[
|
||||
mini_line(80,14,3,0,0,0,[
|
||||
str_block(0,80,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,80,14,3,0,-1,0,0,0,0,0,
|
||||
"if_valid")])
|
||||
])
|
||||
])]).
|
||||
text('#6F367F',80,546,1,1,1,80,17,288418,14,3,0,0,0,0,-65534,80,17,0,0,"",0,0,0,0,560,'',[
|
||||
minilines(80,17,0,0,1,0,0,[
|
||||
mini_line(80,14,3,0,0,0,[
|
||||
str_block(0,80,14,3,0,0,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,80,14,3,0,0,0,0,0,0,0,
|
||||
"if_ready")])
|
||||
])
|
||||
])]).
|
||||
rcbox('#bbde81','',80,280,208,432,1,2,0,0,10,288422,0,0,0,0,'2',0,[
|
||||
]).
|
||||
poly('#009000','',3,[
|
||||
136,432,144,420,152,432],0,2,1,288423,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
text('black',144,296,2,1,1,101,58,288424,24,5,0,0,0,0,2,101,58,0,0,"",0,0,0,0,320,'',[
|
||||
minilines(101,58,0,0,1,0,0,[
|
||||
mini_line(101,24,5,0,0,0,[
|
||||
str_block(0,101,24,5,0,-2,0,0,0,[
|
||||
str_seg('black','Helvetica-Bold',1,138240,101,24,5,0,-2,0,0,0,0,0,
|
||||
"Prefetch")])
|
||||
]),
|
||||
mini_line(75,24,5,0,0,0,[
|
||||
str_block(0,75,24,5,0,-1,0,0,0,[
|
||||
str_seg('black','Helvetica-Bold',1,138240,75,24,5,0,-1,0,0,0,0,0,
|
||||
"Buffer")])
|
||||
])
|
||||
])]).
|
||||
rcbox('#009000','',80,280,208,432,0,2,1,0,10,288425,0,0,0,0,'2',0,[
|
||||
]).
|
||||
text('#6F367F',152,458,1,1,1,50,17,288428,14,3,0,0,0,0,-65534,50,17,0,0,"",0,0,0,0,472,'',[
|
||||
minilines(50,17,0,0,1,0,0,[
|
||||
mini_line(50,14,3,0,0,0,[
|
||||
str_block(0,50,14,3,0,-1,0,0,0,[
|
||||
str_seg('black','Courier-Bold',1,97920,50,14,3,0,-1,0,0,0,0,0,
|
||||
"valid")])
|
||||
])
|
||||
])]).
|
||||
rcbox('#b8cc99','',432,328,560,384,1,2,1,0,10,288430,0,0,0,0,'2',0,[
|
||||
]).
|
||||
rcbox('#3C5A0F','',432,328,560,384,0,2,1,0,10,288431,0,0,0,0,'2',0,[
|
||||
]).
|
||||
text('black',496,337,2,1,1,104,46,288432,18,5,0,0,0,0,2,104,46,0,0,"",0,0,0,0,355,'',[
|
||||
minilines(104,46,0,0,1,0,0,[
|
||||
mini_line(104,18,5,0,0,0,[
|
||||
str_block(0,104,18,5,0,-1,0,0,0,[
|
||||
str_seg('black','Helvetica-Bold',1,115200,104,18,5,0,-1,0,0,0,0,0,
|
||||
"Forwarding")])
|
||||
]),
|
||||
mini_line(67,18,5,0,0,0,[
|
||||
str_block(0,67,18,5,0,-1,0,0,0,[
|
||||
str_seg('black','Helvetica-Bold',1,115200,67,18,5,0,-1,0,0,0,0,0,
|
||||
"Control")])
|
||||
])
|
||||
])]).
|
||||
poly('black','',2,[
|
||||
964,192,964,280],1,1,1,288438,0,0,0,0,0,0,0,'1',0,0,
|
||||
"0","",[
|
||||
0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[
|
||||
]).
|
||||
rcbox('#a5b7d6','',768,280,1040,384,1,2,0,0,10,287905,0,0,0,0,'2',0,[
|
||||
]).
|
||||
rcbox('#1F407A','',768,280,1040,384,0,2,1,0,10,286743,0,0,0,0,'2',0,[
|
||||
]).
|
||||
text('black',824,288,1,1,1,51,29,286745,24,5,0,0,0,0,2,51,29,0,0,"",0,0,0,0,312,'',[
|
||||
minilines(51,29,0,0,1,0,0,[
|
||||
mini_line(51,24,5,0,0,0,[
|
||||
str_block(0,51,24,5,0,-2,0,0,0,[
|
||||
str_seg('black','Helvetica-Bold',1,138240,51,24,5,0,-2,0,0,0,0,0,
|
||||
"LSU")])
|
||||
])
|
||||
])]).
|
||||
poly('black','',2,[
|
||||
904,280,904,384],0,2,1,288448,0,0,5,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('black','',2,[
|
||||
868,192,868,280],1,1,1,288459,0,0,0,0,0,0,0,'1',0,0,
|
||||
"0","",[
|
||||
0,8,3,0,'8','3','0'],[0,8,3,0,'8','3','0'],[
|
||||
]).
|
||||
text('black',896,508,1,1,1,10,20,288462,16,4,0,0,0,0,-65534,10,20,0,0,"",0,0,0,0,524,'',[
|
||||
minilines(10,20,0,0,1,0,0,[
|
||||
mini_line(10,16,4,0,0,0,[
|
||||
str_block(0,10,16,4,0,-1,0,0,0,[
|
||||
str_seg('black','Helvetica-Bold',1,97920,10,16,4,0,-1,0,0,0,0,0,
|
||||
"E")])
|
||||
])
|
||||
])]).
|
||||
text('black',600,508,1,1,1,10,20,288494,16,4,0,0,0,0,-65534,10,20,0,0,"",0,0,0,0,524,'',[
|
||||
minilines(10,20,0,0,1,0,0,[
|
||||
mini_line(10,16,4,0,0,0,[
|
||||
str_block(0,10,16,4,0,-1,0,0,0,[
|
||||
str_seg('black','Helvetica-Bold',1,97920,10,16,4,0,-1,0,0,0,0,0,
|
||||
"E")])
|
||||
])
|
||||
])]).
|
||||
text('black',296,508,1,1,1,10,20,288498,16,4,0,0,0,0,-65534,10,20,0,0,"",0,0,0,0,524,'',[
|
||||
minilines(10,20,0,0,1,0,0,[
|
||||
mini_line(10,16,4,0,0,0,[
|
||||
str_block(0,10,16,4,0,-1,0,0,0,[
|
||||
str_seg('black','Helvetica-Bold',1,97920,10,16,4,0,-1,0,0,0,0,0,
|
||||
"E")])
|
||||
])
|
||||
])]).
|
||||
group([
|
||||
arc('black','',0,2,1,0,744,552,760,568,760,552,760,584,0,32,32,5760,11520,288353,0,0,10,4,0,0,0,'2','10','4',0,[
|
||||
]),
|
||||
poly('black','',4,[
|
||||
760,552,776,552,776,584,760,584],0,2,1,288354,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
])
|
||||
],
|
||||
288516,0,0,[
|
||||
]).
|
||||
poly('black','',3,[
|
||||
744,568,728,568,728,576],0,2,1,288522,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('black','',3,[
|
||||
792,384,792,560,776,560],1,2,1,288531,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('black','',4,[
|
||||
1028,384,1028,520,1028,520,1028,576],0,2,1,288539,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
group([
|
||||
arc('black','',0,2,1,0,440,552,456,568,456,552,456,584,0,32,32,5760,11520,288315,0,0,10,4,0,0,0,'2','10','4',0,[
|
||||
]),
|
||||
poly('black','',4,[
|
||||
456,552,472,552,472,584,456,584],0,2,1,288314,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
])
|
||||
],
|
||||
288544,0,0,[
|
||||
]).
|
||||
poly('black','',2,[
|
||||
424,576,160,576],1,2,1,288560,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('black','',3,[
|
||||
440,568,424,568,424,576],0,2,1,288561,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
group([
|
||||
arc('black','',0,2,1,0,128,552,144,568,144,552,144,584,0,32,32,5760,11520,288574,0,0,10,4,0,0,0,'2','10','4',0,[
|
||||
]),
|
||||
poly('black','',4,[
|
||||
144,552,160,552,160,584,144,584],0,2,1,288573,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
])
|
||||
],
|
||||
288572,0,0,[
|
||||
]).
|
||||
poly('black','',3,[
|
||||
184,432,184,560,160,560],1,2,1,288581,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('black','',2,[
|
||||
128,568,40,568],0,2,1,288588,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
text('black',600,476,1,1,1,12,20,288598,16,4,0,0,0,0,-65534,12,20,0,0,"",0,0,0,0,492,'',[
|
||||
minilines(12,20,0,0,1,0,0,[
|
||||
mini_line(12,16,4,0,0,0,[
|
||||
str_block(0,12,16,4,0,-1,0,0,0,[
|
||||
str_seg('black','Helvetica-Bold',1,97920,12,16,4,0,-1,0,0,0,0,0,
|
||||
"C")])
|
||||
])
|
||||
])]).
|
||||
oval('#A8322D','',536,492,544,500,0,2,1,288611,0,0,0,0,0,'2',0,[
|
||||
]).
|
||||
group([
|
||||
arc('#A8322D','',0,2,1,0,544,472,560,488,560,472,560,504,1,32,32,5760,-11520,288605,0,0,10,4,0,0,0,'2','10','4',0,[
|
||||
]),
|
||||
poly('#A8322D','',4,[
|
||||
560,472,544,472,544,504,560,504],0,2,1,288604,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
])
|
||||
],
|
||||
288603,0,0,[
|
||||
]).
|
||||
poly('#A8322D','',3,[
|
||||
512,576,512,480,544,480],0,2,1,288629,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#3C5A0F','',4,[
|
||||
568,520,528,520,528,496,536,496],0,2,1,288632,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#A8322D','',2,[
|
||||
576,488,592,488],0,2,1,288639,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
oval('#A8322D','',832,492,840,500,0,2,1,288653,0,0,0,0,0,'2',0,[
|
||||
]).
|
||||
group([
|
||||
arc('#A8322D','',0,2,1,0,840,472,856,488,856,472,856,504,1,32,32,5760,-11520,288656,0,0,10,4,0,0,0,'2','10','4',0,[
|
||||
]),
|
||||
poly('#A8322D','',4,[
|
||||
856,472,840,472,840,504,856,504],0,2,1,288655,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
])
|
||||
],
|
||||
288654,0,0,[
|
||||
]).
|
||||
poly('#A8322D','',3,[
|
||||
808,576,808,480,840,480],0,2,1,288657,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#A8322D','',2,[
|
||||
872,488,888,488],0,2,1,288658,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#3C5A0F','',4,[
|
||||
864,520,824,520,824,496,832,496],0,2,1,288668,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
oval('#A8322D','',232,492,240,500,0,2,1,288675,0,0,0,0,0,'2',0,[
|
||||
]).
|
||||
group([
|
||||
arc('#A8322D','',0,2,1,0,240,472,256,488,256,472,256,504,1,32,32,5760,-11520,288678,0,0,10,4,0,0,0,'2','10','4',0,[
|
||||
]),
|
||||
poly('#A8322D','',4,[
|
||||
256,472,240,472,240,504,256,504],0,2,1,288677,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
])
|
||||
],
|
||||
288676,0,0,[
|
||||
]).
|
||||
poly('#A8322D','',3,[
|
||||
208,576,208,480,240,480],0,2,1,288679,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#A8322D','',2,[
|
||||
272,488,288,488],0,2,1,288680,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
poly('#3C5A0F','',4,[
|
||||
256,520,224,520,224,496,232,496],0,2,1,288682,0,0,0,0,0,0,0,'2',0,0,
|
||||
"0","",[
|
||||
0,10,4,0,'10','4','0'],[0,10,4,0,'10','4','0'],[
|
||||
]).
|
||||
text('black',296,476,1,1,1,12,20,288685,16,4,0,0,0,0,-65534,12,20,0,0,"",0,0,0,0,492,'',[
|
||||
minilines(12,20,0,0,1,0,0,[
|
||||
mini_line(12,16,4,0,0,0,[
|
||||
str_block(0,12,16,4,0,-1,0,0,0,[
|
||||
str_seg('black','Helvetica-Bold',1,97920,12,16,4,0,-1,0,0,0,0,0,
|
||||
"C")])
|
||||
])
|
||||
])]).
|
||||
text('black',896,476,1,1,1,12,20,288687,16,4,0,0,0,0,-65534,12,20,0,0,"",0,0,0,0,492,'',[
|
||||
minilines(12,20,0,0,1,0,0,[
|
||||
mini_line(12,16,4,0,0,0,[
|
||||
str_block(0,12,16,4,0,-1,0,0,0,[
|
||||
str_seg('black','Helvetica-Bold',1,97920,12,16,4,0,-1,0,0,0,0,0,
|
||||
"C")])
|
||||
])
|
||||
])]).
|
|
@ -55,6 +55,8 @@
|
|||
|
||||
\usepackage{enumitem}
|
||||
|
||||
\usepackage{tcolorbox}
|
||||
|
||||
\usepackage{pdflscape}
|
||||
|
||||
|
||||
|
@ -115,3 +117,10 @@
|
|||
\textbf{Operation:} \texttt{#2}%
|
||||
}
|
||||
|
||||
\newenvironment{boxnote}%
|
||||
{%
|
||||
\begin{tcolorbox}[colback=red!5!white,colframe=red!75!black,title=Note]%
|
||||
}%
|
||||
{%
|
||||
\end{tcolorbox}%
|
||||
}%
|
||||
|
|
|
@ -64,7 +64,7 @@ module riscv_exc_controller
|
|||
);
|
||||
|
||||
|
||||
enum logic [1:0] { IDLE, WAIT_CONTROLLER, IN_ISR } exc_ctrl_cs, exc_ctrl_ns;
|
||||
enum logic [0:0] { IDLE, WAIT_CONTROLLER } exc_ctrl_cs, exc_ctrl_ns;
|
||||
|
||||
logic req_int;
|
||||
logic [1:0] pc_mux_int, pc_mux_int_q;
|
||||
|
@ -173,7 +173,7 @@ module riscv_exc_controller
|
|||
|
||||
if (ack_i) begin
|
||||
save_cause_o = 1'b1;
|
||||
exc_ctrl_ns = IN_ISR;
|
||||
exc_ctrl_ns = IDLE;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -184,16 +184,10 @@ module riscv_exc_controller
|
|||
|
||||
if (ack_i) begin
|
||||
save_cause_o = 1'b1;
|
||||
exc_ctrl_ns = IN_ISR;
|
||||
exc_ctrl_ns = IDLE;
|
||||
end
|
||||
end
|
||||
|
||||
IN_ISR:
|
||||
begin
|
||||
if (eret_insn_i)
|
||||
exc_ctrl_ns = IDLE;
|
||||
end
|
||||
|
||||
default:
|
||||
begin
|
||||
exc_ctrl_ns = IDLE;
|
||||
|
|
|
@ -140,7 +140,8 @@ module riscv_id_stage
|
|||
output logic [5:0] exc_cause_o,
|
||||
output logic save_exc_cause_o,
|
||||
|
||||
output logic save_pc_id_o,
|
||||
output logic exc_save_id_o,
|
||||
output logic exc_restore_id_o,
|
||||
|
||||
input logic lsu_load_err_i,
|
||||
input logic lsu_store_err_i,
|
||||
|
@ -714,7 +715,8 @@ module riscv_id_stage
|
|||
.exc_ack_o ( exc_ack ),
|
||||
.trap_hit_i ( trap_hit ),
|
||||
|
||||
.save_pc_id_o ( save_pc_id_o ),
|
||||
.exc_save_id_o ( exc_save_id_o ),
|
||||
.exc_restore_id_o ( exc_restore_id_o ),
|
||||
|
||||
// Debug Unit Signals
|
||||
.dbg_stall_i ( dbg_stall_i ),
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
// no traces for synthesis, they are not synthesizable
|
||||
`ifndef SYNTHESIS
|
||||
`define TRACE_EXECUTION
|
||||
//`define SIMCHECKER
|
||||
`endif
|
||||
|
||||
|
||||
|
|
132
riscv_core.sv
132
riscv_core.sv
|
@ -190,11 +190,12 @@ module riscv_core
|
|||
|
||||
// Interrupts
|
||||
logic irq_enable;
|
||||
logic [31:0] epcr;
|
||||
logic [31:0] mepc;
|
||||
|
||||
logic [5:0] exc_cause;
|
||||
logic save_exc_cause;
|
||||
logic save_pc_id;
|
||||
logic exc_save_id;
|
||||
logic exc_restore_id;
|
||||
|
||||
|
||||
// Hardware loop controller signals
|
||||
|
@ -280,7 +281,7 @@ module riscv_core
|
|||
// control signals
|
||||
.clear_instr_valid_i ( clear_instr_valid ),
|
||||
.pc_set_i ( pc_set ),
|
||||
.exception_pc_reg_i ( epcr ), // exception return address
|
||||
.exception_pc_reg_i ( mepc ), // exception return address
|
||||
.pc_mux_i ( pc_mux_id ), // sel for pc multiplexer
|
||||
.exc_pc_mux_i ( exc_pc_mux_id ),
|
||||
.exc_vec_pc_mux_i ( exc_vec_pc_mux_id ),
|
||||
|
@ -425,7 +426,8 @@ module riscv_core
|
|||
.irq_enable_i ( irq_enable ), // global interrupt enable
|
||||
.exc_cause_o ( exc_cause ),
|
||||
.save_exc_cause_o ( save_exc_cause ),
|
||||
.save_pc_id_o ( save_pc_id ), // control signal to save pc
|
||||
.exc_save_id_o ( exc_save_id ), // control signal to save pc
|
||||
.exc_restore_id_o ( exc_restore_id ), // control signal to restore pc
|
||||
.lsu_load_err_i ( lsu_load_err ),
|
||||
.lsu_store_err_i ( lsu_store_err ),
|
||||
|
||||
|
@ -611,10 +613,11 @@ module riscv_core
|
|||
|
||||
// Interrupt related control signals
|
||||
.irq_enable_o ( irq_enable ),
|
||||
.epcr_o ( epcr ),
|
||||
.mepc_o ( mepc ),
|
||||
|
||||
.curr_pc_id_i ( current_pc_id ), // from IF stage
|
||||
.save_pc_id_i ( save_pc_id ),
|
||||
.exc_save_i ( exc_save_id ),
|
||||
.exc_restore_i ( exc_restore_id ),
|
||||
|
||||
.exc_cause_i ( exc_cause ),
|
||||
.save_exc_cause_i ( save_exc_cause ),
|
||||
|
@ -715,47 +718,98 @@ module riscv_core
|
|||
`ifdef TRACE_EXECUTION
|
||||
riscv_tracer riscv_tracer_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
|
||||
.core_id ( core_id_i ),
|
||||
.cluster_id ( cluster_id_i ),
|
||||
.fetch_enable ( fetch_enable_i ),
|
||||
.core_id ( core_id_i ),
|
||||
.cluster_id ( cluster_id_i ),
|
||||
|
||||
.pc ( id_stage_i.current_pc_id_i ),
|
||||
.instr ( id_stage_i.instr ),
|
||||
.compressed ( id_stage_i.is_compressed_i ),
|
||||
.id_valid ( id_stage_i.id_valid_o ),
|
||||
.is_decoding ( id_stage_i.is_decoding_o ),
|
||||
.pipe_flush ( id_stage_i.controller_i.pipe_flush_i ),
|
||||
.pc ( id_stage_i.current_pc_id_i ),
|
||||
.instr ( id_stage_i.instr ),
|
||||
.compressed ( id_stage_i.is_compressed_i ),
|
||||
.id_valid ( id_stage_i.id_valid_o ),
|
||||
.is_decoding ( id_stage_i.is_decoding_o ),
|
||||
.pipe_flush ( id_stage_i.controller_i.pipe_flush_i ),
|
||||
|
||||
.rs1_value ( id_stage_i.operand_a_fw_id ),
|
||||
.rs2_value ( id_stage_i.operand_b_fw_id ),
|
||||
.rs3_value ( id_stage_i.alu_operand_c ),
|
||||
.rs1_value ( id_stage_i.operand_a_fw_id ),
|
||||
.rs2_value ( id_stage_i.operand_b_fw_id ),
|
||||
.rs3_value ( id_stage_i.alu_operand_c ),
|
||||
|
||||
.ex_valid ( ex_valid ),
|
||||
.ex_reg_addr ( regfile_alu_waddr_fw ),
|
||||
.ex_reg_we ( regfile_alu_we_fw ),
|
||||
.ex_reg_wdata ( regfile_alu_wdata_fw ),
|
||||
.ex_valid ( ex_valid ),
|
||||
.ex_reg_addr ( regfile_alu_waddr_fw ),
|
||||
.ex_reg_we ( regfile_alu_we_fw ),
|
||||
.ex_reg_wdata ( regfile_alu_wdata_fw ),
|
||||
|
||||
.ex_data_addr ( data_addr_o ),
|
||||
.ex_data_req ( data_req_o ),
|
||||
.ex_data_gnt ( data_gnt_i ),
|
||||
.ex_data_we ( data_we_o ),
|
||||
.ex_data_wdata ( data_wdata_o ),
|
||||
.ex_data_addr ( data_addr_o ),
|
||||
.ex_data_req ( data_req_o ),
|
||||
.ex_data_gnt ( data_gnt_i ),
|
||||
.ex_data_we ( data_we_o ),
|
||||
.ex_data_wdata ( data_wdata_o ),
|
||||
|
||||
.wb_valid ( wb_valid ),
|
||||
.wb_reg_addr ( regfile_waddr_fw_wb_o ),
|
||||
.wb_reg_we ( regfile_we_wb ),
|
||||
.wb_reg_wdata ( regfile_wdata ),
|
||||
.wb_valid ( wb_valid ),
|
||||
.wb_reg_addr ( regfile_waddr_fw_wb_o ),
|
||||
.wb_reg_we ( regfile_we_wb ),
|
||||
.wb_reg_wdata ( regfile_wdata ),
|
||||
|
||||
.imm_u_type ( id_stage_i.imm_u_type ),
|
||||
.imm_uj_type ( id_stage_i.imm_uj_type ),
|
||||
.imm_i_type ( id_stage_i.imm_i_type ),
|
||||
.imm_iz_type ( id_stage_i.imm_iz_type[11:0] ),
|
||||
.imm_z_type ( id_stage_i.imm_z_type ),
|
||||
.imm_s_type ( id_stage_i.imm_s_type ),
|
||||
.imm_sb_type ( id_stage_i.imm_sb_type )
|
||||
.imm_u_type ( id_stage_i.imm_u_type ),
|
||||
.imm_uj_type ( id_stage_i.imm_uj_type ),
|
||||
.imm_i_type ( id_stage_i.imm_i_type ),
|
||||
.imm_iz_type ( id_stage_i.imm_iz_type[11:0] ),
|
||||
.imm_z_type ( id_stage_i.imm_z_type ),
|
||||
.imm_s_type ( id_stage_i.imm_s_type ),
|
||||
.imm_sb_type ( id_stage_i.imm_sb_type )
|
||||
);
|
||||
`endif
|
||||
|
||||
`ifdef SIMCHECKER
|
||||
logic is_interrupt;
|
||||
assign is_interrupt = (pc_mux_id == `PC_EXCEPTION) && (exc_pc_mux_id == `EXC_PC_IRQ);
|
||||
|
||||
riscv_simchecker riscv_simchecker_i
|
||||
(
|
||||
.clk ( clk ),
|
||||
.rst_n ( rst_n ),
|
||||
|
||||
.fetch_enable ( fetch_enable_i ),
|
||||
.boot_addr ( boot_addr_i ),
|
||||
.core_id ( core_id_i ),
|
||||
.cluster_id ( cluster_id_i ),
|
||||
|
||||
.instr_compressed ( if_stage_i.fetch_rdata[15:0] ),
|
||||
.pc_set ( pc_set ),
|
||||
.if_valid ( if_valid ),
|
||||
|
||||
.pc ( id_stage_i.current_pc_id_i ),
|
||||
.instr ( id_stage_i.instr ),
|
||||
.is_compressed ( is_compressed_id ),
|
||||
.id_valid ( id_stage_i.id_valid_o ),
|
||||
.is_decoding ( id_stage_i.is_decoding_o ),
|
||||
.is_illegal ( id_stage_i.illegal_insn_dec ),
|
||||
.is_interrupt ( is_interrupt ),
|
||||
.irq_no ( exc_vec_pc_mux_id ),
|
||||
.pipe_flush ( id_stage_i.controller_i.pipe_flush_i ),
|
||||
|
||||
.ex_valid ( ex_valid ),
|
||||
.ex_reg_addr ( id_stage_i.registers_i.waddr_b_i ),
|
||||
.ex_reg_we ( id_stage_i.registers_i.we_b_i ),
|
||||
.ex_reg_wdata ( id_stage_i.registers_i.wdata_b_i ),
|
||||
|
||||
.ex_data_addr ( data_addr_o ),
|
||||
.ex_data_req ( data_req_o ),
|
||||
.ex_data_gnt ( data_gnt_i ),
|
||||
.ex_data_we ( data_we_o ),
|
||||
.ex_data_wdata ( data_wdata_o ),
|
||||
|
||||
.lsu_misaligned ( data_misaligned ),
|
||||
|
||||
.wb_valid ( wb_valid ),
|
||||
.wb_reg_addr ( id_stage_i.registers_i.waddr_a_i ),
|
||||
.wb_reg_we ( id_stage_i.registers_i.we_a_i ),
|
||||
.wb_reg_wdata ( id_stage_i.registers_i.wdata_a_i ),
|
||||
|
||||
.wb_data_rvalid ( data_rvalid_i ),
|
||||
.wb_data_rdata ( data_rdata_i )
|
||||
);
|
||||
`endif
|
||||
|
||||
|
|
309
riscv_simchecker.sv
Normal file
309
riscv_simchecker.sv
Normal file
|
@ -0,0 +1,309 @@
|
|||
// Copyright 2015 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.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Engineer: Andreas Traber - atraber@iis.ee.ethz.ch //
|
||||
// //
|
||||
// Additional contributions by: //
|
||||
// //
|
||||
// Design Name: RISC-V Tracer //
|
||||
// Project Name: RI5CY //
|
||||
// Language: SystemVerilog //
|
||||
// //
|
||||
// Description: Compares the executed instructions with a golden model //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
import "DPI-C" function chandle riscv_checker_init(input int boot_addr, input int core_id, input int cluster_id);
|
||||
import "DPI-C" function int riscv_checker_step(input chandle cpu, input longint simtime, input int cycle, input logic [31:0] pc, input logic [31:0] instr);
|
||||
import "DPI-C" function void riscv_checker_irq(input chandle cpu, input int irq, input int irq_no);
|
||||
import "DPI-C" function void riscv_checker_mem_access(input chandle cpu, input int we, input logic [31:0] addr, input logic [31:0] data);
|
||||
import "DPI-C" function void riscv_checker_reg_access(input chandle cpu, input logic [31:0] addr, input logic [31:0] data);
|
||||
|
||||
module riscv_simchecker
|
||||
(
|
||||
// Clock and Reset
|
||||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
input logic fetch_enable,
|
||||
input logic [31:0] boot_addr,
|
||||
input logic [4:0] core_id,
|
||||
input logic [4:0] cluster_id,
|
||||
|
||||
input logic [15:0] instr_compressed,
|
||||
input logic if_valid,
|
||||
input logic pc_set,
|
||||
|
||||
input logic [31:0] pc,
|
||||
input logic [31:0] instr,
|
||||
input logic is_compressed,
|
||||
input logic id_valid,
|
||||
input logic is_decoding,
|
||||
input logic is_illegal,
|
||||
input logic is_interrupt,
|
||||
input logic [4:0] irq_no,
|
||||
input logic pipe_flush,
|
||||
|
||||
input logic ex_valid,
|
||||
input logic [ 4:0] ex_reg_addr,
|
||||
input logic ex_reg_we,
|
||||
input logic [31:0] ex_reg_wdata,
|
||||
|
||||
input logic ex_data_req,
|
||||
input logic ex_data_gnt,
|
||||
input logic ex_data_we,
|
||||
input logic [31:0] ex_data_addr,
|
||||
input logic [31:0] ex_data_wdata,
|
||||
|
||||
input logic lsu_misaligned,
|
||||
|
||||
input logic wb_valid,
|
||||
input logic [ 4:0] wb_reg_addr,
|
||||
input logic wb_reg_we,
|
||||
input logic [31:0] wb_reg_wdata,
|
||||
|
||||
input logic wb_data_rvalid,
|
||||
input logic [31:0] wb_data_rdata
|
||||
);
|
||||
|
||||
// DPI stuff
|
||||
chandle dpi_simdata;
|
||||
|
||||
// SV-only stuff
|
||||
typedef struct {
|
||||
logic [ 4:0] addr;
|
||||
logic [31:0] value;
|
||||
} reg_t;
|
||||
|
||||
typedef struct {
|
||||
logic [31:0] addr;
|
||||
logic we;
|
||||
logic [ 3:0] be;
|
||||
logic [31:0] wdata;
|
||||
logic [31:0] rdata;
|
||||
} mem_acc_t;
|
||||
|
||||
class instr_trace_t;
|
||||
time simtime;
|
||||
int cycles;
|
||||
logic [31:0] pc;
|
||||
logic [31:0] instr;
|
||||
logic irq;
|
||||
logic [ 4:0] irq_no;
|
||||
reg_t regs_write[$];
|
||||
mem_acc_t mem_access[$];
|
||||
|
||||
function new ();
|
||||
irq = 1'b0;
|
||||
regs_write = {};
|
||||
mem_access = {};
|
||||
endfunction
|
||||
endclass
|
||||
|
||||
mailbox rdata_stack = new (4);
|
||||
integer rdata_writes = 0;
|
||||
|
||||
integer cycles;
|
||||
|
||||
logic [15:0] instr_compressed_id;
|
||||
logic is_irq_if, is_irq_id;
|
||||
logic [ 4:0] irq_no_id, irq_no_if;
|
||||
|
||||
mailbox instr_ex = new (2);
|
||||
mailbox instr_wb = new (2);
|
||||
|
||||
// simchecker initialization
|
||||
initial
|
||||
begin
|
||||
wait(rst_n == 1'b1);
|
||||
wait(fetch_enable == 1'b1);
|
||||
|
||||
dpi_simdata = riscv_checker_init(boot_addr, core_id, cluster_id);
|
||||
end
|
||||
|
||||
// virtual ID/EX pipeline
|
||||
initial
|
||||
begin
|
||||
instr_trace_t trace;
|
||||
mem_acc_t mem_acc;
|
||||
reg_t reg_write;
|
||||
|
||||
while(1) begin
|
||||
instr_ex.get(trace);
|
||||
|
||||
// wait until we are going to the next stage
|
||||
do begin
|
||||
@(negedge clk);
|
||||
|
||||
reg_write.addr = ex_reg_addr;
|
||||
reg_write.value = ex_reg_wdata;
|
||||
|
||||
if (ex_reg_we)
|
||||
trace.regs_write.push_back(reg_write);
|
||||
|
||||
// look for data accesses and log them
|
||||
if (ex_data_req && ex_data_gnt) begin
|
||||
mem_acc.addr = ex_data_addr;
|
||||
mem_acc.we = ex_data_we;
|
||||
|
||||
if (mem_acc.we)
|
||||
mem_acc.wdata = ex_data_wdata;
|
||||
else
|
||||
mem_acc.wdata = 'x;
|
||||
|
||||
trace.mem_access.push_back(mem_acc);
|
||||
end
|
||||
end while (!ex_valid || lsu_misaligned);
|
||||
|
||||
instr_wb.put(trace);
|
||||
end
|
||||
end
|
||||
|
||||
// virtual EX/WB pipeline
|
||||
initial
|
||||
begin
|
||||
instr_trace_t trace;
|
||||
reg_t reg_write;
|
||||
logic [31:0] tmp_discard;
|
||||
|
||||
while(1) begin
|
||||
instr_wb.get(trace);
|
||||
|
||||
// wait until we are going to the next stage
|
||||
do begin
|
||||
@(negedge clk);
|
||||
#1;
|
||||
|
||||
// pop rdata from stack when there were pending writes
|
||||
while(rdata_stack.num() > 0 && rdata_writes > 0) begin
|
||||
rdata_writes--;
|
||||
rdata_stack.get(tmp_discard);
|
||||
end
|
||||
|
||||
end while (!wb_valid);
|
||||
|
||||
reg_write.addr = wb_reg_addr;
|
||||
reg_write.value = wb_reg_wdata;
|
||||
|
||||
if (wb_reg_we)
|
||||
trace.regs_write.push_back(reg_write);
|
||||
|
||||
// keep care of rdata
|
||||
foreach(trace.mem_access[i]) begin
|
||||
if (trace.mem_access[i].we) begin
|
||||
// for writes we don't need to wait for the rdata, so if it has
|
||||
// not appeared yet, we count it and remove it later from out
|
||||
// stack
|
||||
rdata_writes++;
|
||||
|
||||
end else begin
|
||||
if (rdata_stack.num() == 0)
|
||||
$warning("rdata stack is empty, but we are waiting for a read");
|
||||
|
||||
rdata_stack.get(trace.mem_access[i].rdata);
|
||||
end
|
||||
end
|
||||
|
||||
// instruction is ready now, all data is inserted
|
||||
foreach(trace.mem_access[i]) begin
|
||||
if (trace.mem_access[i].we)
|
||||
riscv_checker_mem_access(dpi_simdata, trace.mem_access[i].we, trace.mem_access[i].addr, trace.mem_access[i].wdata);
|
||||
else
|
||||
riscv_checker_mem_access(dpi_simdata, trace.mem_access[i].we, trace.mem_access[i].addr, trace.mem_access[i].rdata);
|
||||
end
|
||||
|
||||
foreach(trace.regs_write[i]) begin
|
||||
riscv_checker_reg_access(dpi_simdata, trace.regs_write[i].addr, trace.regs_write[i].value);
|
||||
end
|
||||
|
||||
riscv_checker_irq(dpi_simdata, trace.irq, trace.irq_no);
|
||||
|
||||
if (riscv_checker_step(dpi_simdata, trace.simtime, trace.cycles, trace.pc, trace.instr))
|
||||
$display("%t: Cluster %d, Core %d: Mismatch between simulator and RTL detected", trace.simtime, cluster_id, core_id);
|
||||
end
|
||||
end
|
||||
|
||||
// cycle counter
|
||||
always_ff @(posedge clk, negedge rst_n)
|
||||
begin
|
||||
if (rst_n == 1'b0)
|
||||
cycles = 0;
|
||||
else
|
||||
cycles = cycles + 1;
|
||||
end
|
||||
|
||||
// create rdata stack
|
||||
initial
|
||||
begin
|
||||
while(1) begin
|
||||
@(negedge clk);
|
||||
|
||||
if (wb_data_rvalid) begin
|
||||
rdata_stack.put(wb_data_rdata);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk)
|
||||
begin
|
||||
if (pc_set) begin
|
||||
is_irq_if <= is_interrupt;
|
||||
irq_no_if <= irq_no;
|
||||
end else if (if_valid) begin
|
||||
is_irq_if <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk)
|
||||
begin
|
||||
if (if_valid) begin
|
||||
instr_compressed_id <= instr_compressed;
|
||||
is_irq_id <= is_irq_if;
|
||||
irq_no_id <= irq_no_if;
|
||||
end
|
||||
end
|
||||
|
||||
// log execution
|
||||
initial
|
||||
begin
|
||||
instr_trace_t trace;
|
||||
|
||||
while(1) begin
|
||||
@(negedge clk);
|
||||
|
||||
// - special case for WFI because we don't wait for unstalling there
|
||||
// - special case for illegal instructions, since they will not go through
|
||||
// the pipe
|
||||
if ((id_valid && is_decoding) || pipe_flush || (is_decoding && is_illegal))
|
||||
begin
|
||||
trace = new ();
|
||||
|
||||
trace.simtime = $time;
|
||||
trace.cycles = cycles;
|
||||
trace.pc = pc;
|
||||
|
||||
if (is_compressed)
|
||||
trace.instr = {instr_compressed_id, instr_compressed_id};
|
||||
else
|
||||
trace.instr = instr;
|
||||
|
||||
if (is_irq_id) begin
|
||||
trace.irq = 1'b1;
|
||||
trace.irq_no = irq_no_id;
|
||||
end
|
||||
|
||||
instr_ex.put(trace);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
|
@ -30,6 +30,7 @@ module riscv_tracer
|
|||
input logic clk,
|
||||
input logic rst_n,
|
||||
|
||||
input logic fetch_enable,
|
||||
input logic [4:0] core_id,
|
||||
input logic [4:0] cluster_id,
|
||||
|
||||
|
@ -67,7 +68,6 @@ module riscv_tracer
|
|||
input logic [31:0] imm_z_type,
|
||||
input logic [31:0] imm_s_type,
|
||||
input logic [31:0] imm_sb_type
|
||||
|
||||
);
|
||||
|
||||
integer f;
|
||||
|
@ -187,7 +187,7 @@ module riscv_tracer
|
|||
function void printUInstr(input string mnemonic);
|
||||
begin
|
||||
regs_write.push_back({rd, 'x});
|
||||
str = $sformatf("%-16s x%0d, 0x%0h000", mnemonic, rd, imm_u_type[31:12]);
|
||||
str = $sformatf("%-16s x%0d, 0x%0h", mnemonic, rd, {imm_u_type[31:12], 12'h000});
|
||||
end
|
||||
endfunction // printUInstr
|
||||
|
||||
|
@ -375,11 +375,13 @@ module riscv_tracer
|
|||
// open/close output file for writing
|
||||
initial
|
||||
begin
|
||||
#1 // delay needed for valid core_id and cluster_id
|
||||
wait(rst_n == 1'b1);
|
||||
wait(fetch_enable == 1'b1);
|
||||
$sformat(fn, "trace_core_%h_%h.log", cluster_id, core_id);
|
||||
$display("[TRACER] Output filename is: %s", fn);
|
||||
f = $fopen(fn, "w");
|
||||
$fwrite(f, "%20s\t%6s\t%10s\t%10s\t \t%s\n", "Time", "Cycles", "PC", "Instr", "Mnemonic");
|
||||
$fwrite(f, " Time Cycles PC Instr Mnemonic\n");
|
||||
|
||||
end
|
||||
|
||||
final
|
||||
|
@ -403,7 +405,7 @@ module riscv_tracer
|
|||
|
||||
// wait until we are going to the next stage
|
||||
do begin
|
||||
@(posedge clk);
|
||||
@(negedge clk);
|
||||
|
||||
// replace register written back
|
||||
foreach(trace.regs_write[i])
|
||||
|
@ -438,7 +440,7 @@ module riscv_tracer
|
|||
|
||||
// wait until we are going to the next stage
|
||||
do begin
|
||||
@(posedge clk);
|
||||
@(negedge clk);
|
||||
|
||||
// replace register written back
|
||||
foreach(trace.regs_write[i])
|
||||
|
@ -451,7 +453,7 @@ module riscv_tracer
|
|||
end
|
||||
|
||||
// log execution
|
||||
always @(posedge clk)
|
||||
always @(negedge clk)
|
||||
begin
|
||||
instr_trace_t trace;
|
||||
|
||||
|
@ -502,10 +504,10 @@ module riscv_tracer
|
|||
`INSTR_SRA: trace.printRInstr("sra");
|
||||
`INSTR_OR: trace.printRInstr("or");
|
||||
`INSTR_AND: trace.printRInstr("and");
|
||||
`INSTR_EXTHS: trace.printRInstr("exths");
|
||||
`INSTR_EXTHZ: trace.printRInstr("exthz");
|
||||
`INSTR_EXTBS: trace.printRInstr("extbs");
|
||||
`INSTR_EXTBZ: trace.printRInstr("extbz");
|
||||
`INSTR_EXTHS: trace.printRInstr("p.exths");
|
||||
`INSTR_EXTHZ: trace.printRInstr("p.exthz");
|
||||
`INSTR_EXTBS: trace.printRInstr("p.extbs");
|
||||
`INSTR_EXTBZ: trace.printRInstr("p.extbz");
|
||||
`INSTR_PAVG: trace.printRInstr("p.avg");
|
||||
`INSTR_PAVGU: trace.printRInstr("p.avgu");
|
||||
`INSTR_PSLET: trace.printRInstr("p.slet");
|
||||
|
@ -545,7 +547,4 @@ module riscv_tracer
|
|||
end
|
||||
end // always @ (posedge clk)
|
||||
|
||||
|
||||
|
||||
|
||||
endmodule
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue