1 |
2 |
mcafruni |
--------------------------------------------------------------------------
|
2 |
|
|
-- --
|
3 |
|
|
-- --
|
4 |
|
|
-- miniMIPS Superscalar Processor : Coprocessor system (cop0) --
|
5 |
|
|
-- based on miniMIPS Processor --
|
6 |
|
|
-- --
|
7 |
|
|
-- --
|
8 |
|
|
-- Author : Miguel Cafruni --
|
9 |
|
|
-- miguel_cafruni@hotmail.com --
|
10 |
|
|
-- December 2018 --
|
11 |
|
|
--------------------------------------------------------------------------
|
12 |
|
|
|
13 |
|
|
library ieee;
|
14 |
|
|
use ieee.std_logic_1164.all;
|
15 |
|
|
use IEEE.numeric_std.all;
|
16 |
|
|
|
17 |
|
|
library work;
|
18 |
|
|
use work.pack_mips.all;
|
19 |
|
|
|
20 |
|
|
-- By convention in the commentary, the term interruption means hardware interruptions and software exceptions
|
21 |
|
|
|
22 |
|
|
entity syscop is
|
23 |
|
|
port
|
24 |
|
|
(
|
25 |
|
|
clock : in std_logic;
|
26 |
|
|
reset : in std_logic;
|
27 |
|
|
|
28 |
|
|
-- Datas from the pipeline
|
29 |
|
|
MEM_adr : in bus32; -- Address (PC) of the current instruction in the pipeline end -> responsible of the exception
|
30 |
|
|
MEM_exc_cause : in bus32; -- Potential cause exception of that instruction
|
31 |
|
|
MEM_it_ok : in std_logic; -- Allow hardware interruptions
|
32 |
|
|
|
33 |
|
|
-- Hardware interruption
|
34 |
|
|
it_mat : in std_logic; -- Hardware interruption detected
|
35 |
|
|
|
36 |
|
|
-- Interruption controls
|
37 |
|
|
interrupt : out std_logic; -- Interruption to take into account
|
38 |
|
|
vecteur_it : out bus32; -- Interruption vector
|
39 |
|
|
|
40 |
|
|
-- Writing request in register bank
|
41 |
|
|
write_data : in bus32; -- Data to write
|
42 |
|
|
write_adr : in bus5; -- Address of the register to write
|
43 |
|
|
write_SCP : in std_logic; -- Writing request
|
44 |
|
|
|
45 |
|
|
-- Reading request in register bank
|
46 |
|
|
read_adr1 : in bus5; -- Address of the first register
|
47 |
|
|
read_adr2 : in bus5; -- Address of the second register
|
48 |
|
|
read_data1 : out bus32; -- Value of register 1
|
49 |
|
|
read_data2 : out bus32; -- Value of register 2
|
50 |
|
|
|
51 |
|
|
-- Datas from the pipeline
|
52 |
|
|
MEM_adr2 : in bus32; -- Address of the current instruction in the pipeline end -> responsible of the exception
|
53 |
|
|
MEM_exc_cause2 : in bus32; -- Potential cause exception of that instruction
|
54 |
|
|
MEM_it_ok2 : in std_logic; -- Allow hardware interruptions
|
55 |
|
|
|
56 |
|
|
-- Hardware interruption
|
57 |
|
|
--it_mat2 : in std_logic; -- Hardware interruption detected
|
58 |
|
|
|
59 |
|
|
-- Interruption controls
|
60 |
|
|
--interrupt : out std_logic; -- Interruption to take into account
|
61 |
|
|
--vecteur_it : out bus32; -- Interruption vector
|
62 |
|
|
|
63 |
|
|
-- Writing request in register bank
|
64 |
|
|
write_data2 : in bus32; -- Data to write
|
65 |
|
|
write_adr2 : in bus5; -- Address of the register to write
|
66 |
|
|
write_SCP2 : in std_logic; -- Writing request
|
67 |
|
|
|
68 |
|
|
-- Reading request in register bank
|
69 |
|
|
read_adr3 : in bus5; -- Address of the 3th register
|
70 |
|
|
read_adr4 : in bus5; -- Address of the 4th register
|
71 |
|
|
read_data3 : out bus32; -- Value of register 3
|
72 |
|
|
read_data4 : out bus32 -- Value of register 4
|
73 |
|
|
);
|
74 |
|
|
end syscop;
|
75 |
|
|
|
76 |
|
|
|
77 |
|
|
architecture rtl of syscop is
|
78 |
|
|
|
79 |
|
|
subtype adr_scp_reg is integer range 12 to 15;
|
80 |
|
|
|
81 |
|
|
type scp_reg_type is array (integer range adr_scp_reg'low to adr_scp_reg'high) of bus32;
|
82 |
|
|
|
83 |
|
|
-- Constants to define the coprocessor registers
|
84 |
|
|
constant COMMAND : integer := 0; -- False register to command the coprocessor system
|
85 |
|
|
constant STATUS : adr_scp_reg := 12; -- Registre 12 of the coprocessor system
|
86 |
|
|
constant CAUSE : adr_scp_reg := 13; -- Registre 13 of the coprocessor system
|
87 |
|
|
constant ADRESSE : adr_scp_reg := 14; -- Registre 14 of the coprocessor system
|
88 |
|
|
constant VECTIT : adr_scp_reg := 15; -- Registre 15 of the coprocessor system
|
89 |
|
|
|
90 |
|
|
signal scp_reg : scp_reg_type; -- Internal register bank
|
91 |
|
|
signal pre_reg : scp_reg_type; -- Register bank preparation
|
92 |
|
|
|
93 |
|
|
signal adr_src1 : integer range 0 to 31;
|
94 |
|
|
signal adr_src2 : integer range 0 to 31;
|
95 |
|
|
signal adr_dest : integer range 0 to 31;
|
96 |
|
|
--mod
|
97 |
|
|
signal adr_src3 : integer range 0 to 31;
|
98 |
|
|
signal adr_src4 : integer range 0 to 31;
|
99 |
|
|
signal adr_dest2 : integer range 0 to 31;
|
100 |
|
|
--fim mod
|
101 |
|
|
signal exception, exception2 : std_logic; -- Set to '1' when exception detected *** quando MEM_exc_cause for diferente de IT_NOEXC
|
102 |
|
|
signal interruption, interruption2 : std_logic; -- Set to '1' when interruption detected
|
103 |
|
|
signal cmd_itret : std_logic; -- Set to '1' when interruption return command is detected
|
104 |
|
|
|
105 |
|
|
signal save_msk : std_logic; -- Save the mask state when an interruption occurs
|
106 |
|
|
|
107 |
|
|
begin
|
108 |
|
|
|
109 |
|
|
-- Detection of the interruptions
|
110 |
|
|
exception <= '1' when MEM_exc_cause/=IT_NOEXC else '0'; -- *** chegou uma instrucao ilegal ou break ou syscall ***
|
111 |
|
|
exception2 <= '1' when MEM_exc_cause2/=IT_NOEXC else '0'; -- *** chegou uma instrucao ilegal ou break ou syscall ***
|
112 |
|
|
interruption <= '1' when it_mat='1' and scp_reg(STATUS)(0)='1' and MEM_it_ok='1' else '0';
|
113 |
|
|
interruption2 <= '1' when it_mat='1' and scp_reg(STATUS)(0)='1' and MEM_it_ok2='1' else '0';
|
114 |
|
|
-- Update asynchronous outputs
|
115 |
|
|
interrupt <= exception or exception2 or interruption or interruption2; -- Detection of interruptions
|
116 |
|
|
vecteur_it <= scp_reg(ADRESSE) when cmd_itret = '1' else -- Send the return adress when a return instruction appears -- *** retorno de uma instrucao ilegal ou break ou syscall ***
|
117 |
|
|
scp_reg(VECTIT); -- Send the interruption vector in other cases
|
118 |
|
|
|
119 |
|
|
|
120 |
|
|
-- Decode the address of the registers
|
121 |
|
|
adr_src1 <= to_integer(unsigned(read_adr1));
|
122 |
|
|
adr_src2 <= to_integer(unsigned(read_adr2));
|
123 |
|
|
adr_dest <= to_integer(unsigned(write_adr));
|
124 |
|
|
--mod
|
125 |
|
|
adr_src3 <= to_integer(unsigned(read_adr3));
|
126 |
|
|
adr_src4 <= to_integer(unsigned(read_adr4));
|
127 |
|
|
adr_dest2 <= to_integer(unsigned(write_adr2));
|
128 |
|
|
--fim mod
|
129 |
|
|
-- Read the two registers
|
130 |
|
|
read_data1 <= (others => '0') when (adr_src1<scp_reg'low or adr_src1>scp_reg'high) else
|
131 |
|
|
scp_reg(adr_src1);
|
132 |
|
|
read_data2 <= (others => '0') when (adr_src2<scp_reg'low or adr_src2>scp_reg'high) else
|
133 |
|
|
scp_reg(adr_src2);
|
134 |
|
|
--mod
|
135 |
|
|
-- Read the two registers
|
136 |
|
|
read_data3 <= (others => '0') when (adr_src3<scp_reg'low or adr_src3>scp_reg'high) else
|
137 |
|
|
scp_reg(adr_src3);
|
138 |
|
|
read_data4 <= (others => '0') when (adr_src4<scp_reg'low or adr_src4>scp_reg'high) else -- erro de copia e cola
|
139 |
|
|
scp_reg(adr_src4); -- arrumado em 04\12\17
|
140 |
|
|
--fim mod
|
141 |
|
|
|
142 |
|
|
-- Define the pre_reg signal, next value for the registers
|
143 |
|
|
process (scp_reg, adr_dest, write_SCP, write_data, interruption, interruption2,--process (scp_reg, adr_dest, write_SCP, write_data, interruption,
|
144 |
|
|
exception, exception2, MEM_exc_cause, MEM_adr, reset, adr_dest2, write_SCP2, write_data2, MEM_exc_cause2, MEM_adr2)--exception, MEM_exc_cause, MEM_adr, reset)
|
145 |
|
|
begin -- *** exception eh um sinal interno e tambem pode ser tratado em um processo *** --
|
146 |
|
|
pre_reg <= scp_reg;
|
147 |
|
|
cmd_itret <= '0'; -- No IT return in most cases
|
148 |
|
|
|
149 |
|
|
-- Potential writing in a register
|
150 |
|
|
if (write_SCP='1' and adr_dest>=pre_reg'low and adr_dest<=pre_reg'high) then
|
151 |
|
|
pre_reg(adr_dest) <= write_data;
|
152 |
|
|
end if;
|
153 |
|
|
--mod
|
154 |
|
|
-- Potential writing in a register from 2nd pipe
|
155 |
|
|
if (write_SCP2='1' and adr_dest2>=pre_reg'low and adr_dest2<=pre_reg'high) then
|
156 |
|
|
pre_reg(adr_dest2) <= write_data2;
|
157 |
|
|
end if;
|
158 |
|
|
--fim mod
|
159 |
|
|
|
160 |
|
|
-- Command from the core
|
161 |
|
|
if write_SCP='1' and adr_dest=COMMAND then
|
162 |
|
|
case write_data is -- Different operations
|
163 |
|
|
when SYS_UNMASK => pre_reg(STATUS)(0) <= '1'; -- Unamsk command
|
164 |
|
|
when SYS_MASK => pre_reg(STATUS)(0) <= '0'; -- Mask command
|
165 |
|
|
when SYS_ITRET => -- Interruption return command
|
166 |
|
|
pre_reg(STATUS)(0) <= save_msk; -- Restore the mask before the interruption
|
167 |
|
|
cmd_itret <= '1'; -- False interruption request (to clear the pipeline)
|
168 |
|
|
when others => null;
|
169 |
|
|
end case;
|
170 |
|
|
end if;
|
171 |
|
|
|
172 |
|
|
-- Modifications from the interruptions
|
173 |
|
|
if interruption='1' then
|
174 |
|
|
pre_reg(STATUS)(0) <= '0'; -- Mask the interruptions
|
175 |
|
|
pre_reg(CAUSE) <= IT_ITMAT; -- Save the interruption cause
|
176 |
|
|
pre_reg(ADRESSE) <= MEM_adr; -- Save the return address
|
177 |
|
|
end if;
|
178 |
|
|
|
179 |
|
|
-- Modifications from the interruptions
|
180 |
|
|
if interruption2='1' then
|
181 |
|
|
pre_reg(STATUS)(0) <= '0'; -- Mask the interruptions
|
182 |
|
|
pre_reg(CAUSE) <= IT_ITMAT; -- Save the interruption cause
|
183 |
|
|
pre_reg(ADRESSE) <= MEM_adr2; -- Save the return address
|
184 |
|
|
end if;
|
185 |
|
|
|
186 |
|
|
-- Modifications from the exceptions
|
187 |
|
|
if exception='1' then -- *** chegou uma instrucao ilegal ou break ou syscall ***
|
188 |
|
|
pre_reg(STATUS)(0) <= '0'; -- Mask the interruptions
|
189 |
|
|
pre_reg(CAUSE) <= MEM_exc_cause; -- Save the exception cause
|
190 |
|
|
pre_reg(ADRESSE) <= MEM_adr; -- Save the return address
|
191 |
|
|
end if;
|
192 |
|
|
|
193 |
|
|
-- Modifications from the exceptions
|
194 |
|
|
if exception2='1' then -- *** chegou uma instrucao ilegal ou break ou syscall ***
|
195 |
|
|
pre_reg(STATUS)(0) <= '0'; -- Mask the interruptions
|
196 |
|
|
pre_reg(CAUSE) <= MEM_exc_cause2; -- Save the exception cause
|
197 |
|
|
pre_reg(ADRESSE) <= MEM_adr2; -- Save the return address
|
198 |
|
|
end if;
|
199 |
|
|
-- The reset has the priority on the other cuases
|
200 |
|
|
if reset='1' then
|
201 |
|
|
pre_reg <= (others => (others => '0'));
|
202 |
|
|
|
203 |
|
|
-- NB : The processor is masked after a reset
|
204 |
|
|
-- The exception handler is set at address 0
|
205 |
|
|
end if;
|
206 |
|
|
end process;
|
207 |
|
|
|
208 |
|
|
-- Memorisation of the modifications in the register bank
|
209 |
|
|
process(clock)
|
210 |
|
|
begin
|
211 |
|
|
if clock='1' and clock'event then
|
212 |
|
|
-- Save the mask when an interruption appears
|
213 |
|
|
if (exception='1') or (interruption='1') or (exception2='1') or (interruption2='1') then
|
214 |
|
|
save_msk <= scp_reg(STATUS)(0);
|
215 |
|
|
end if;
|
216 |
|
|
scp_reg <= pre_reg;
|
217 |
|
|
end if;
|
218 |
|
|
end process;
|
219 |
|
|
|
220 |
|
|
end rtl;
|