URL
https://opencores.org/ocsvn/potato/potato/trunk
Subversion Repositories potato
Compare Revisions
- This comparison shows the changes necessary to convert path
/potato/branches
- from Rev 52 to Rev 53
- ↔ Reverse comparison
Rev 52 → Rev 53
/new-privileged-isa/src/pp_execute.vhd
17,8 → 17,9
|
stall, flush : in std_logic; |
|
-- IRQ input: |
-- Interrupt inputs: |
irq : in std_logic_vector(7 downto 0); |
software_interrupt, timer_interrupt : in std_logic; |
|
-- Data memory outputs: |
dmem_address : out std_logic_vector(31 downto 0); |
77,9 → 78,11
count_instruction_out : out std_logic; |
|
-- Exception control registers: |
status_in : in csr_status_register; |
evec_in : in std_logic_vector(31 downto 0); |
evec_out : out std_logic_vector(31 downto 0); |
ie_in, ie1_in : in std_logic; |
mie_in : in std_logic_vector(31 downto 0); |
mtvec_in : in std_logic_vector(31 downto 0); |
mtvec_out : out std_logic_vector(31 downto 0); |
--mepc_in : in std_logic_vector(31 downto 0); |
|
-- Exception signals: |
decode_exception_in : in std_logic; |
143,8 → 146,8
signal do_jump : std_logic; |
signal jump_target : std_logic_vector(31 downto 0); |
|
signal sr : csr_status_register; |
signal evec, evec_forwarded : std_logic_vector(31 downto 0); |
signal mtvec, mtvec_forwarded : std_logic_vector(31 downto 0); |
signal mie, mie_forwarded : std_logic_vector(31 downto 0); |
|
signal csr_write : csr_write_mode; |
signal csr_addr : csr_address; |
158,7 → 161,7
|
signal exception_taken : std_logic; |
signal exception_cause : csr_exception_cause; |
signal exception_vaddr : std_logic_vector(31 downto 0); |
signal exception_addr : std_logic_vector(31 downto 0); |
|
signal exception_context_forwarded : csr_exception_context; |
|
185,9 → 188,10
|
exception_out <= exception_taken; |
exception_context_out <= ( |
status => exception_context_forwarded.status, |
ie => exception_context_forwarded.ie, |
ie1 => exception_context_forwarded.ie1, |
cause => exception_cause, |
badvaddr => exception_vaddr |
badaddr => exception_addr |
) when exception_taken = '1' else exception_context_forwarded; |
|
do_jump <= (to_std_logic(branch = BRANCH_JUMP or branch = BRANCH_JUMP_INDIRECT) |
196,19 → 200,19
jump_out <= do_jump; |
jump_target_out <= jump_target; |
|
evec_out <= evec_forwarded; |
exception_taken <= (decode_exception or to_std_logic(exception_cause /= CSR_CAUSE_NONE) or irq_asserted) and not stall; |
mtvec_out <= std_logic_vector(unsigned(mtvec_forwarded) + CSR_MTVEC_M_OFFSET); |
exception_taken <= not stall and (decode_exception or to_std_logic(exception_cause /= CSR_CAUSE_NONE)); |
|
irq_asserted <= to_std_logic(exception_context_forwarded.status.ei = '1' and |
(irq and exception_context_forwarded.status.im) /= x"00"); |
irq_asserted <= to_std_logic(exception_context_forwarded.ie = '1' and (irq and mie_forwarded(31 downto 24)) /= x"00"); |
|
rs1_data <= rs1_data_in; |
rs2_data <= rs2_data_in; |
|
dmem_address <= alu_result; |
dmem_address <= alu_result when (mem_op /= MEMOP_TYPE_NONE and mem_op /= MEMOP_TYPE_INVALID) and exception_taken = '0' |
else (others => '0'); |
dmem_data_out <= rs2_forwarded; |
dmem_write_req <= '1' when mem_op = MEMOP_TYPE_STORE else '0'; |
dmem_read_req <= '1' when memop_is_load(mem_op) else '0'; |
dmem_write_req <= '1' when mem_op = MEMOP_TYPE_STORE and exception_taken = '0' else '0'; |
dmem_read_req <= '1' when memop_is_load(mem_op) and exception_taken = '0' else '0'; |
|
pipeline_register: process(clk) |
begin |
251,11 → 255,9
csr_use_immediate <= csr_use_immediate_in; |
csr_writeable <= csr_writeable_in; |
|
-- Status register; |
sr <= status_in; |
|
-- Exception vector base: |
evec <= evec_in; |
mtvec <= mtvec_in; |
mie <= mie_in; |
|
-- Instruction decoder exceptions: |
decode_exception <= decode_exception_in; |
278,13 → 280,13
end case; |
end process set_data_size; |
|
get_irq_num: process(irq, exception_context_forwarded) |
get_irq_num: process(irq, exception_context_forwarded, mie_forwarded) |
variable temp : std_logic_vector(3 downto 0); |
begin |
temp := (others => '0'); |
|
for i in 0 to 7 loop |
if irq(i) = '1' and exception_context_forwarded.status.im(i) = '1' then |
if irq(i) = '1' and mie_forwarded(24 + i) = '1' then |
temp := std_logic_vector(to_unsigned(i, temp'length)); |
exit; |
end if; |
323,10 → 325,15
end process instr_misalign_check; |
|
find_exception_cause: process(decode_exception, decode_exception_cause, mem_op, |
data_misaligned, instr_misaligned, irq_asserted, irq_asserted_num) |
data_misaligned, instr_misaligned, irq_asserted, irq_asserted_num, mie_forwarded, |
software_interrupt, timer_interrupt, exception_context_forwarded) |
begin |
if irq_asserted = '1' then |
exception_cause <= std_logic_vector(unsigned(CSR_CAUSE_IRQ_BASE) + unsigned(irq_asserted_num)); |
elsif software_interrupt = '1' and mie_forwarded(CSR_MIE_MSIE) = '1' and exception_context_forwarded.ie = '1' then |
exception_cause <= CSR_CAUSE_SOFTWARE_INT; |
elsif timer_interrupt = '1' and mie_forwarded(CSR_MIE_MTIE) = '1' and exception_context_forwarded.ie = '1' then |
exception_cause <= CSR_CAUSE_TIMER_INT; |
elsif decode_exception = '1' then |
exception_cause <= decode_exception_cause; |
elsif mem_op = MEMOP_TYPE_INVALID then |
342,16 → 349,16
end if; |
end process find_exception_cause; |
|
find_exception_vaddr: process(instr_misaligned, data_misaligned, jump_target, alu_result) |
find_exception_addr: process(instr_misaligned, data_misaligned, jump_target, alu_result) |
begin |
if instr_misaligned = '1' then |
exception_vaddr <= jump_target; |
exception_addr <= jump_target; |
elsif data_misaligned = '1' then |
exception_vaddr <= alu_result; |
exception_addr <= alu_result; |
else |
exception_vaddr <= (others => '0'); |
exception_addr <= (others => '0'); |
end if; |
end process find_exception_vaddr; |
end process find_exception_addr; |
|
calc_jump_tgt: process(branch, pc, rs1_forwarded, immediate, csr_value_forwarded) |
begin |
361,7 → 368,7
when BRANCH_JUMP_INDIRECT => |
jump_target <= std_logic_vector(unsigned(rs1_forwarded) + unsigned(immediate)); |
when BRANCH_SRET => |
jump_target <= csr_value_forwarded; -- Will be the EPC value in the case of SRET |
jump_target <= csr_value_forwarded; |
when others => |
jump_target <= (others => '0'); |
end case; |
417,20 → 424,20
csr_value, mem_csr_value, wb_csr_value, csr_writeable, mem_exception, wb_exception, |
mem_exception_context, wb_exception_context) |
begin |
if csr_addr = CSR_CAUSE and mem_exception = '1' then |
if csr_addr = CSR_MCAUSE and mem_exception = '1' then |
csr_value_forwarded <= to_std_logic_vector(mem_exception_context.cause); |
elsif csr_addr = CSR_STATUS and mem_exception = '1' then |
csr_value_forwarded <= to_std_logic_vector(mem_exception_context.status); |
elsif csr_addr = CSR_BADVADDR and mem_exception = '1' then |
csr_value_forwarded <= mem_exception_context.badvaddr; |
elsif csr_addr = CSR_MSTATUS and mem_exception = '1' then |
csr_value_forwarded <= csr_make_mstatus(mem_exception_context.ie, mem_exception_context.ie1); |
elsif csr_addr = CSR_MBADADDR and mem_exception = '1' then |
csr_value_forwarded <= mem_exception_context.badaddr; |
elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = csr_addr and csr_writeable then |
csr_value_forwarded <= mem_csr_value; |
elsif csr_addr = CSR_CAUSE and wb_exception = '1' then |
elsif csr_addr = CSR_MCAUSE and wb_exception = '1' then |
csr_value_forwarded <= to_std_logic_vector(wb_exception_context.cause); |
elsif csr_addr = CSR_STATUS and wb_exception = '1' then |
csr_value_forwarded <= to_std_logic_vector(wb_exception_context.status); |
elsif csr_addr = CSR_BADVADDR and wb_exception = '1' then |
csr_value_forwarded <= wb_exception_context.badvaddr; |
elsif csr_addr = CSR_MSTATUS and wb_exception = '1' then |
csr_value_forwarded <= csr_make_mstatus(wb_exception_context.ie, wb_exception_context.ie1); |
elsif csr_addr = CSR_MBADADDR and wb_exception = '1' then |
csr_value_forwarded <= wb_exception_context.badaddr; |
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = csr_addr and csr_writeable then |
csr_value_forwarded <= wb_csr_value; |
else |
438,40 → 445,55
end if; |
end process csr_forward; |
|
evec_forward: process(mem_csr_write, mem_csr_addr, mem_csr_value, |
wb_csr_write, wb_csr_addr, wb_csr_value, evec) |
mtvec_forward: process(mem_csr_write, mem_csr_addr, mem_csr_value, |
wb_csr_write, wb_csr_addr, wb_csr_value, mtvec) |
begin |
if mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_EVEC then |
evec_forwarded <= mem_csr_value; |
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_EVEC then |
evec_forwarded <= wb_csr_value; |
if mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_MTVEC then |
mtvec_forwarded <= mem_csr_value; |
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_MTVEC then |
mtvec_forwarded <= wb_csr_value; |
else |
evec_forwarded <= evec; |
mtvec_forwarded <= mtvec; |
end if; |
end process evec_forward; |
end process mtvec_forward; |
|
mie_forward: process(mem_csr_write, mem_csr_addr, mem_csr_value, |
wb_csr_write, wb_csr_addr, wb_csr_value, mie) |
begin |
if mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_MIE then |
mie_forwarded <= mem_csr_value; |
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_MIE then |
mie_forwarded <= wb_csr_value; |
else |
mie_forwarded <= mie; |
end if; |
end process mie_forward; |
|
exception_ctx_forward: process(mem_exception, wb_exception, mem_exception_context, wb_exception_context, |
exception_cause, exception_vaddr, mem_csr_write, mem_csr_addr, mem_csr_value, |
wb_csr_write, wb_csr_addr, wb_csr_value, sr) |
exception_cause, exception_addr, mem_csr_write, mem_csr_addr, mem_csr_value, |
wb_csr_write, wb_csr_addr, wb_csr_value, ie_in, ie1_in) |
begin |
if mem_exception = '1' then |
exception_context_forwarded <= mem_exception_context; |
elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_STATUS then |
elsif mem_csr_write /= CSR_WRITE_NONE and mem_csr_addr = CSR_MSTATUS then |
exception_context_forwarded <= ( |
status => to_csr_status_register(mem_csr_value), |
cause => mem_exception_context.cause, |
badvaddr => mem_exception_context.badvaddr); |
ie => mem_csr_value(CSR_SR_IE), |
ie1 => mem_csr_value(CSR_SR_IE1), |
cause => exception_cause, |
badaddr => exception_addr); |
elsif wb_exception = '1' then |
exception_context_forwarded <= wb_exception_context; |
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_STATUS then |
elsif wb_csr_write /= CSR_WRITE_NONE and wb_csr_addr = CSR_MSTATUS then |
exception_context_forwarded <= ( |
status => to_csr_status_register(wb_csr_value), |
cause => wb_exception_context.cause, |
badvaddr => wb_exception_context.badvaddr); |
ie => wb_csr_value(CSR_SR_IE), |
ie1 => wb_csr_value(CSR_SR_IE1), |
cause => exception_cause, |
badaddr => exception_addr); |
else |
exception_context_forwarded.status <= sr; |
exception_context_forwarded.ie <= ie_in; |
exception_context_forwarded.ie1 <= ie1_in; |
exception_context_forwarded.cause <= exception_cause; |
exception_context_forwarded.badvaddr <= exception_vaddr; |
exception_context_forwarded.badaddr <= exception_addr; |
end if; |
end process exception_ctx_forward; |
|
/new-privileged-isa/src/pp_potato.vhd
12,7 → 12,7
entity pp_potato is |
generic( |
PROCESSOR_ID : std_logic_vector(31 downto 0) := x"00000000"; --! Processor ID. |
RESET_ADDRESS : std_logic_vector(31 downto 0) := x"00000000" --! Address of the first instruction to execute. |
RESET_ADDRESS : std_logic_vector(31 downto 0) := x"00000200" --! Address of the first instruction to execute. |
); |
port( |
clk : in std_logic; |
/new-privileged-isa/src/pp_memory.vhd
84,7 → 84,7
mem_op <= MEMOP_TYPE_NONE; |
rd_write_out <= '0'; |
csr_write_out <= CSR_WRITE_REPLACE; |
csr_addr_out <= CSR_EPC; |
csr_addr_out <= CSR_MEPC; |
csr_data_out <= pc; |
count_instr_out <= '0'; |
else |
108,27 → 108,20
exception_out <= exception_in or to_std_logic(branch = BRANCH_SRET); |
|
if exception_in = '1' then |
exception_context_out.status <= ( |
pim => exception_context_in.status.im, |
im => (others => '0'), |
pei => exception_context_in.status.ei, |
ei => '0' |
); |
exception_context_out.ie <= '0'; |
exception_context_out.ie1 <= exception_context_in.ie; |
exception_context_out.cause <= exception_context_in.cause; |
exception_context_out.badvaddr <= exception_context_in.badvaddr; |
exception_context_out.badaddr <= exception_context_in.badaddr; |
elsif branch = BRANCH_SRET then |
exception_context_out.status <= ( |
pim => exception_context_in.status.pim, |
im => exception_context_in.status.pim, |
pei => exception_context_in.status.pei, |
ei => exception_context_in.status.pei |
); |
exception_context_out.ie <= exception_context_in.ie1; |
exception_context_out.ie1 <= exception_context_in.ie; |
exception_context_out.cause <= CSR_CAUSE_NONE; |
exception_context_out.badvaddr <= (others => '0'); |
exception_context_out.badaddr <= (others => '0'); |
else |
exception_context_out.status <= exception_context_in.status; |
exception_context_out.ie <= exception_context_in.ie; |
exception_context_out.ie1 <= exception_context_in.ie1; |
exception_context_out.cause <= CSR_CAUSE_NONE; |
exception_context_out.badvaddr <= (others => '0'); |
exception_context_out.badaddr <= (others => '0'); |
end if; |
end if; |
end if; |
/new-privileged-isa/src/pp_control_unit.vhd
25,7 → 25,7
|
-- Exception signals: |
decode_exception : out std_logic; |
decode_exception_cause : out std_logic_vector(4 downto 0); |
decode_exception_cause : out csr_exception_cause; |
|
-- Control register signals: |
csr_write : out csr_write_mode; |
45,7 → 45,7
|
architecture behaviour of pp_control_unit is |
signal exception : std_logic; |
signal exception_cause : std_logic_vector(4 downto 0); |
signal exception_cause : csr_exception_cause; |
signal alu_op_temp : alu_operation; |
begin |
|
125,13 → 125,13
|
if funct12 = x"000" then |
exception <= '1'; |
exception_cause <= CSR_CAUSE_SYSCALL; |
exception_cause <= CSR_CAUSE_ECALL; |
branch <= BRANCH_NONE; |
elsif funct12 = x"001" then |
exception <= '1'; |
exception_cause <= CSR_CAUSE_BREAKPOINT; |
branch <= BRANCH_NONE; |
elsif funct12 = x"800" then |
elsif funct12 = CSR_EPC_ERET then |
exception <= '0'; |
exception_cause <= CSR_CAUSE_NONE; |
branch <= BRANCH_SRET; |
/new-privileged-isa/src/pp_decode.vhd
111,8 → 111,8
|
decode_csr_addr: process(immediate_value) |
begin |
if immediate_value(11 downto 0) = CSR_EPC_SRET then |
csr_addr <= CSR_EPC; |
if immediate_value(11 downto 0) = CSR_EPC_ERET then |
csr_addr <= CSR_MEPC; |
else |
csr_addr <= immediate_value(11 downto 0); |
end if; |
/new-privileged-isa/src/pp_csr_unit.vhd
7,6 → 7,7
use ieee.numeric_std.all; |
|
use work.pp_csr.all; |
use work.pp_utilities.all; |
|
entity pp_csr_unit is |
generic( |
16,6 → 17,9
clk, timer_clk : in std_logic; |
reset : in std_logic; |
|
-- IRQ signals: |
irq : in std_logic_vector(7 downto 0); |
|
-- Count retired instruction: |
count_instruction : in std_logic; |
|
39,35 → 43,58
exception_context : in csr_exception_context; |
exception_context_write : in std_logic; |
|
-- Interrupts originating from this unit: |
software_interrupt_out : out std_logic; |
timer_interrupt_out : out std_logic; |
|
-- Registers needed for exception handling, always read: |
status_out : out csr_status_register; |
evec_out : out std_logic_vector(31 downto 0) |
mie_out : out std_logic_vector(31 downto 0); |
mtvec_out : out std_logic_vector(31 downto 0); |
ie_out, ie1_out : out std_logic |
); |
end entity pp_csr_unit; |
|
architecture behaviour of pp_csr_unit is |
|
-- Implemented counters: |
-- Counters: |
signal counter_time : std_logic_vector(63 downto 0); |
signal counter_cycle : std_logic_vector(63 downto 0); |
signal counter_instret : std_logic_vector(63 downto 0); |
|
-- Implemented registers: |
signal sup0, sup1 : std_logic_vector(31 downto 0) := (others => '0'); |
signal epc, evec : std_logic_vector(31 downto 0) := (others => '0'); |
signal badvaddr : std_logic_vector(31 downto 0) := (others => '0'); |
signal cause : csr_exception_cause; |
-- Machine time counter: |
signal counter_mtime : std_logic_vector(31 downto 0); |
signal mtime_compare : std_logic_vector(31 downto 0); |
|
-- Machine-mode registers: |
signal mcause : csr_exception_cause; |
signal mbadaddr : std_logic_vector(31 downto 0); |
signal mscratch : std_logic_vector(31 downto 0); |
signal mepc : std_logic_vector(31 downto 0); |
signal mtvec : std_logic_vector(31 downto 0) := x"00000100"; |
signal mie : std_logic_vector(31 downto 0) := (others => '0'); |
|
-- Interrupt enable bits: |
signal ie, ie1 : std_logic; |
|
-- HTIF FROMHOST register: |
signal fromhost: std_logic_vector(31 downto 0); |
|
-- Status register: |
signal status_register : csr_status_register; |
-- Interrupt signals: |
signal timer_interrupt : std_logic; |
signal software_interrupt : std_logic; |
|
begin |
|
read_writeable <= csr_is_writeable(read_address); |
-- Interrupt signals: |
software_interrupt_out <= software_interrupt; |
timer_interrupt_out <= timer_interrupt; |
ie_out <= ie; |
ie1_out <= ie1; |
mie_out <= mie; |
|
-- The two upper bits of the CSR address encodes the accessibility of the CSR: |
read_writeable <= read_address(11 downto 10) /= b"11"; |
|
--! Updates the FROMHOST register when new data is available. |
htif_fromhost: process(clk) |
begin |
86,7 → 113,7
tohost_data <= (others => '0'); |
tohost_updated <= '0'; |
else |
if write_mode /= CSR_WRITE_NONE and write_address = CSR_TOHOST then |
if write_mode /= CSR_WRITE_NONE and write_address = CSR_MTOHOST then |
tohost_data <= write_data_in; |
tohost_updated <= '1'; |
else |
96,32 → 123,67
end if; |
end process htif_tohost; |
|
mtime_counter: process(timer_clk, reset) |
begin |
if reset = '1' then -- Asynchronous reset because timer_clk is slower than clk |
counter_mtime <= (others => '0'); |
elsif rising_edge(timer_clk) then |
counter_mtime <= std_logic_vector(unsigned(counter_mtime) + 1); |
end if; |
end process mtime_counter; |
|
mtime_interrupt: process(clk) |
begin |
if rising_edge(clk) then |
if reset = '1' then |
timer_interrupt <= '0'; |
else |
if write_mode /= CSR_WRITE_NONE and write_address = CSR_MTIMECMP then |
timer_interrupt <= '0'; |
elsif counter_mtime = mtime_compare then |
timer_interrupt <= '1'; |
end if; |
end if; |
end if; |
end process mtime_interrupt; |
|
write: process(clk) |
begin |
if rising_edge(clk) then |
if reset = '1' then |
status_register <= CSR_SR_DEFAULT; |
software_interrupt <= '0'; |
mtvec <= x"00000100"; |
mepc <= x"00000100"; |
mie <= (others => '0'); |
ie <= '0'; |
ie1 <= '0'; |
else |
if exception_context_write = '1' then |
status_register <= exception_context.status; |
cause <= exception_context.cause; |
badvaddr <= exception_context.badvaddr; |
ie <= exception_context.ie; |
ie1 <= exception_context.ie1; |
mcause <= exception_context.cause; |
mbadaddr <= exception_context.badaddr; |
end if; |
|
if write_mode /= CSR_WRITE_NONE then |
case write_address is |
when CSR_STATUS => |
if exception_context_write = '0' then |
status_register <= to_csr_status_register(write_data_in); |
end if; |
when CSR_EPC => |
epc <= write_data_in; |
when CSR_EVEC => |
evec <= write_data_in; |
when CSR_SUP0 => |
sup0 <= write_data_in; |
when CSR_SUP1 => |
sup1 <= write_data_in; |
when CSR_MSTATUS => -- Status register |
ie1 <= write_data_in(CSR_SR_IE1); |
ie <= write_data_in(CSR_SR_IE); |
when CSR_MSCRATCH => -- Scratch register |
mscratch <= write_data_in; |
when CSR_MEPC => -- Exception return address |
mepc <= write_data_in; |
--when CSR_MCAUSE => -- Exception cause |
-- mcause <= write_data_in(31) & write_data_in(4 downto 0); |
when CSR_MTVEC => -- Exception vector address |
mtvec <= write_data_in; |
when CSR_MTIMECMP => -- Time compare register |
mtime_compare <= write_data_in; |
when CSR_MIE => -- Interrupt enable register: |
mie <= write_data_in; |
when CSR_MIP => -- Interrupt pending register: |
software_interrupt <= write_data_in(CSR_MIP_MSIP); |
when others => |
-- Ignore writes to invalid or read-only registers |
end case; |
130,21 → 192,14
end if; |
end process write; |
|
status_out <= exception_context.status when exception_context_write = '1' else status_register; |
|
read: process(clk) |
begin |
if rising_edge(clk) then |
--if exception_context_write = '1' then |
-- status_out <= exception_context.status; |
--else |
-- status_out <= status_register; |
--end if; |
|
if write_mode /= CSR_WRITE_NONE and write_address = CSR_EVEC then |
evec_out <= write_data_in; |
if write_mode /= CSR_WRITE_NONE and write_address = CSR_MTVEC then |
mtvec_out <= write_data_in; |
else |
evec_out <= evec; |
mtvec_out <= mtvec; |
end if; |
|
if write_mode /= CSR_WRITE_NONE and write_address = read_address then |
151,30 → 206,46
read_data_out <= write_data_in; |
else |
case read_address is |
|
-- Status and control registers: |
when CSR_STATUS => -- Status register |
read_data_out <= to_std_logic_vector(status_register); |
when CSR_HARTID => -- Processor ID |
|
-- Machine mode registers: |
when CSR_MCPUID => -- CPU features register |
read_data_out <= ( |
8 => '1', -- Set the bit corresponding to I |
others => '0'); |
when CSR_MIMPID => -- Implementation/Implementor ID |
read_data_out <= (31 downto 16 => '0') & x"8000"; |
-- The anonymous source ID, 0x8000 is used until an open-source implementation ID |
-- is available for use. |
when CSR_MHARTID => -- Hardware thread ID |
read_data_out <= PROCESSOR_ID; |
when CSR_FROMHOST => -- Fromhost data |
when CSR_MFROMHOST => -- Data from a host environment |
read_data_out <= fromhost; |
when CSR_EPC | CSR_EPC_SRET => -- Exception PC value |
read_data_out <= epc; |
when CSR_EVEC => -- Exception handler address |
read_data_out <= evec; |
when CSR_CAUSE => -- Exception cause |
read_data_out <= to_std_logic_vector(cause); |
when CSR_BADVADDR => -- Load/store address responsible for the exception |
read_data_out <= badvaddr; |
when CSR_MSTATUS => -- Status register |
read_data_out <= csr_make_mstatus(ie, ie1); |
when CSR_MSCRATCH => -- Scratch register |
read_data_out <= mscratch; |
when CSR_MEPC => -- Exception PC value |
read_data_out <= mepc; |
when CSR_MTVEC => -- Exception vector address |
read_data_out <= mtvec; |
when CSR_MTDELEG => -- Exception vector delegation register, unsupported |
read_data_out <= (others => '0'); |
when CSR_MIP => -- Interrupt pending |
read_data_out <= irq & (CSR_MIP_MTIP => timer_interrupt, CSR_MIP_MSIP => software_interrupt, |
23 downto 8 => '0', 6 downto 4 => '0', 2 downto 0 => '0'); |
when CSR_MIE => -- Interrupt enable register |
read_data_out <= mie; |
when CSR_MBADADDR => -- Bad memory address |
read_data_out <= mbadaddr; |
when CSR_MCAUSE => -- Exception cause |
read_data_out <= mcause(5) & (30 downto 5 => '0') & mcause(4 downto 0); --to_std_logic_vector(mcause); |
|
-- Supporting registers: |
when CSR_SUP0 => |
read_data_out <= sup0; |
when CSR_SUP1 => |
read_data_out <= sup1; |
|
-- Timers and counters: |
when CSR_MTIME => -- Machine time counter register |
read_data_out <= counter_mtime; |
when CSR_MTIMECMP => -- Machine time compare register |
read_data_out <= mtime_compare; |
|
when CSR_TIME => |
read_data_out <= counter_time(31 downto 0); |
when CSR_TIMEH => |
/new-privileged-isa/src/pp_csr.vhd
12,8 → 12,9
subtype csr_address is std_logic_vector(11 downto 0); |
|
--! Type used for exception cause values. |
subtype csr_exception_cause is std_logic_vector(4 downto 0); |
subtype csr_exception_cause is std_logic_vector(5 downto 0); -- Upper bit is the interrupt bit |
|
--! Converts an exception cause to a std_logic_vector. |
function to_std_logic_vector(input : in csr_exception_cause) return std_logic_vector; |
|
--! Control/status register write mode: |
22,28 → 23,22
); |
|
-- Exception cause values: |
constant CSR_CAUSE_INSTR_MISALIGN : csr_exception_cause := b"00000"; |
constant CSR_CAUSE_INSTR_FETCH : csr_exception_cause := b"00001"; |
constant CSR_CAUSE_INVALID_INSTR : csr_exception_cause := b"00010"; |
constant CSR_CAUSE_SYSCALL : csr_exception_cause := b"00110"; |
constant CSR_CAUSE_BREAKPOINT : csr_exception_cause := b"00111"; |
constant CSR_CAUSE_LOAD_MISALIGN : csr_exception_cause := b"01000"; |
constant CSR_CAUSE_STORE_MISALIGN : csr_exception_cause := b"01001"; |
constant CSR_CAUSE_LOAD_ERROR : csr_exception_cause := b"01010"; |
constant CSR_CAUSE_STORE_ERROR : csr_exception_cause := b"01011"; |
constant CSR_CAUSE_FROMHOST : csr_exception_cause := b"11110"; |
constant CSR_CAUSE_NONE : csr_exception_cause := b"11111"; |
constant CSR_CAUSE_INSTR_MISALIGN : csr_exception_cause := b"000000"; |
constant CSR_CAUSE_INSTR_FETCH : csr_exception_cause := b"000001"; |
constant CSR_CAUSE_INVALID_INSTR : csr_exception_cause := b"000010"; |
constant CSR_CAUSE_BREAKPOINT : csr_exception_cause := b"000011"; |
constant CSR_CAUSE_LOAD_MISALIGN : csr_exception_cause := b"000100"; |
constant CSR_CAUSE_LOAD_ERROR : csr_exception_cause := b"000101"; |
constant CSR_CAUSE_STORE_MISALIGN : csr_exception_cause := b"000110"; |
constant CSR_CAUSE_STORE_ERROR : csr_exception_cause := b"000111"; |
constant CSR_CAUSE_ECALL : csr_exception_cause := b"001011"; |
constant CSR_CAUSE_NONE : csr_exception_cause := b"011111"; |
|
constant CSR_CAUSE_IRQ_BASE : csr_exception_cause := b"10000"; |
constant CSR_CAUSE_SOFTWARE_INT : csr_exception_cause := b"100000"; |
constant CSR_CAUSE_TIMER_INT : csr_exception_cause := b"100001"; |
constant CSR_CAUSE_IRQ_BASE : csr_exception_cause := b"110000"; |
|
-- Control register IDs, specified in the immediate of csr* instructions: |
constant CSR_STATUS : csr_address := x"50a"; |
constant CSR_HARTID : csr_address := x"50b"; |
constant CSR_SUP0 : csr_address := x"500"; |
constant CSR_SUP1 : csr_address := x"501"; |
constant CSR_BADVADDR : csr_address := x"503"; |
constant CSR_TOHOST : csr_address := x"51e"; |
constant CSR_FROMHOST : csr_address := x"51f"; |
-- Control register IDs, specified in the immediate field of csr* instructions: |
constant CSR_CYCLE : csr_address := x"c00"; |
constant CSR_CYCLEH : csr_address := x"c80"; |
constant CSR_TIME : csr_address := x"c01"; |
50,57 → 45,61
constant CSR_TIMEH : csr_address := x"c81"; |
constant CSR_INSTRET : csr_address := x"c02"; |
constant CSR_INSTRETH : csr_address := x"c82"; |
constant CSR_EPC : csr_address := x"502"; |
constant CSR_EVEC : csr_address := x"508"; |
constant CSR_CAUSE : csr_address := x"509"; |
|
-- Values used as control register IDs in SRET, SCALL and SBREAK: |
constant CSR_EPC_SRET : csr_address := x"800"; |
constant CSR_MCPUID : csr_address := x"f00"; |
constant CSR_MIMPID : csr_address := x"f01"; |
constant CSR_MHARTID : csr_address := x"f10"; |
|
constant CSR_MSTATUS : csr_address := x"300"; |
constant CSR_MTVEC : csr_address := x"301"; |
constant CSR_MTDELEG : csr_address := x"302"; |
constant CSR_MIE : csr_address := x"304"; |
|
constant CSR_MTIMECMP : csr_address := x"321"; |
constant CSR_MTIME : csr_address := x"701"; |
|
constant CSR_MSCRATCH : csr_address := x"340"; |
constant CSR_MEPC : csr_address := x"341"; |
constant CSR_MCAUSE : csr_address := x"342"; |
constant CSR_MBADADDR : csr_address := x"343"; |
constant CSR_MIP : csr_address := x"344"; |
|
constant CSR_MTOHOST : csr_address := x"780"; |
constant CSR_MFROMHOST : csr_address := x"781"; |
|
-- Values used as control register IDs in ERET: |
constant CSR_EPC_ERET : csr_address := x"100"; |
|
-- Offset into the exception vector for handling machine-mode exceptions: |
constant CSR_MTVEC_M_OFFSET : natural := 192; |
|
-- Additional CSRs from supervisor mode that aliases machine mode registers |
-- in this implementation: |
--constant CSR_STVEC : csr_address := x"101"; |
--constant CSR_SEPC : csr_address := x"141"; |
|
-- Status register bit indices: |
constant CSR_SR_S : natural := 0; |
constant CSR_SR_PS : natural := 1; |
constant CSR_SR_EI : natural := 2; |
constant CSR_SR_PEI : natural := 3; |
constant CSR_SR_IE : natural := 0; |
constant CSR_SR_IE1 : natural := 3; |
|
-- Status register in Potato: |
-- * Bit 0, S: Supervisor mode, always 1 |
-- * Bit 1, PS: Previous supervisor mode bit, always 1 |
-- * Bit 2, EI: Enable interrupts bit |
-- * Bit 3, PEI: Previous enable interrupts bit |
-- * Bits 23 downto 16, IM: Interrupt mask |
-- * Bits 31 downto 24, PIM: Previous interrupt mask |
-- MIE and MIP register bit indices: |
constant CSR_MIE_MSIE : natural := 3; |
constant CSR_MIE_MTIE : natural := 7; |
constant CSR_MIP_MSIP : natural := CSR_MIE_MSIE; |
constant CSR_MIP_MTIP : natural := CSR_MIE_MTIE; |
|
-- Status register record: |
type csr_status_register is |
record |
ei, pei : std_logic; |
im, pim : std_logic_vector(7 downto 0); |
end record; |
|
-- Exception context; this record contains all state that is stored |
-- Exception context; this record contains all state that can be manipulated |
-- when an exception is taken. |
type csr_exception_context is |
record |
status : csr_status_register; |
cause : csr_exception_cause; |
badvaddr : std_logic_vector(31 downto 0); |
ie, ie1 : std_logic; -- Enable Interrupt bits |
cause : csr_exception_cause; |
badaddr : std_logic_vector(31 downto 0); |
end record; |
|
-- Reset value of the status register: |
constant CSR_SR_DEFAULT : csr_status_register := (ei => '0', pei => '0', im => x"00", pim => x"00"); |
--! Creates the value of the mstatus registe from the EI and EI1 bits. |
function csr_make_mstatus(ie, ie1 : in std_logic) return std_logic_vector; |
|
-- Converts a status register record into an std_logic_vector: |
function to_std_logic_vector(input : in csr_status_register) |
return std_logic_vector; |
|
-- Converts an std_logic_vector into a status register record: |
function to_csr_status_register(input : in std_logic_vector(31 downto 0)) |
return csr_status_register; |
|
--! Checks if a control register is writeable. |
function csr_is_writeable(csr : in csr_address) return boolean; |
|
end package pp_csr; |
|
package body pp_csr is |
108,37 → 107,21
function to_std_logic_vector(input : in csr_exception_cause) |
return std_logic_vector is |
begin |
return (31 downto 5 => '0') & input; |
return (31 => input(5), 30 downto 5 => '0') & input(4 downto 0); |
end function to_std_logic_vector; |
|
function to_std_logic_vector(input : in csr_status_register) |
return std_logic_vector is |
function csr_make_mstatus(ie, ie1 : in std_logic) return std_logic_vector is |
variable retval : std_logic_vector(31 downto 0); |
begin |
return input.pim & input.im & (15 downto 4 => '0') & input.pei & input.ei & '1' & '1'; |
end function to_std_logic_vector; |
|
function to_csr_status_register(input : in std_logic_vector(31 downto 0)) |
return csr_status_register |
is |
variable retval : csr_status_register; |
begin |
retval.ei := input(CSR_SR_EI); |
retval.pei := input(CSR_SR_PEI); |
retval.im := input(23 downto 16); |
retval.pim := input(31 downto 24); |
retval := ( |
11 downto 10 => '1', -- PRV3 |
8 downto 7 => '1', -- PRV2 |
5 downto 4 => '1', -- PRV1 |
CSR_SR_IE1 => ie1, -- IE1 |
2 downto 1 => '1', -- PRV |
CSR_SR_IE => ie, -- IE |
others => '0'); |
return retval; |
end function to_csr_status_register; |
end function csr_make_mstatus; |
|
function csr_is_writeable(csr : in csr_address) return boolean is |
begin |
case csr is |
when CSR_FROMHOST | CSR_CYCLE | CSR_CYCLEH | CSR_HARTID |
| CSR_TIME | CSR_TIMEH | CSR_INSTRET | CSR_INSTRETH |
| CSR_CAUSE | CSR_BADVADDR => |
return false; |
when others => |
return true; |
end case; |
end function csr_is_writeable; |
|
end package body pp_csr; |
/new-privileged-isa/src/pp_core.vhd
19,7 → 19,7
entity pp_core is |
generic( |
PROCESSOR_ID : std_logic_vector(31 downto 0) := x"00000000"; --! Processor ID. |
RESET_ADDRESS : std_logic_vector(31 downto 0) := x"00000000" --! Address of the first instruction to execute. |
RESET_ADDRESS : std_logic_vector(31 downto 0) := x"00000200" --! Address of the first instruction to execute. |
); |
port( |
-- Control inputs: |
67,7 → 67,7
-- by the instret counter: |
signal if_count_instruction, id_count_instruction : std_logic; |
signal ex_count_instruction, mem_count_instruction : std_logic; |
signal wb_count_instruction : std_logic; |
signal wb_count_instruction : std_logic; |
|
-- CSR read port signals: |
signal csr_read_data : std_logic_vector(31 downto 0); |
75,9 → 75,13
signal csr_read_address, csr_read_address_p : csr_address; |
|
-- Status register outputs: |
signal status : csr_status_register; |
signal evec : std_logic_vector(31 downto 0); |
signal mtvec : std_logic_vector(31 downto 0); |
signal mie : std_logic_vector(31 downto 0); |
signal ie, ie1 : std_logic; |
|
-- Internal interrupt signals: |
signal software_interrupt, timer_interrupt : std_logic; |
|
-- Load hazard detected in the execute stage: |
signal load_hazard_detected : std_logic; |
|
182,6 → 186,7
clk => clk, |
reset => reset, |
timer_clk => timer_clk, |
irq => irq, |
count_instruction => wb_count_instruction, |
fromhost_data => fromhost_data, |
fromhost_updated => fromhost_write_en, |
195,12 → 200,15
write_mode => wb_csr_write, |
exception_context => wb_exception_context, |
exception_context_write => wb_exception, |
status_out => status, |
evec_out => evec |
mie_out => mie, |
mtvec_out => mtvec, |
ie_out => ie, |
ie1_out => ie1, |
software_interrupt_out => software_interrupt, |
timer_interrupt_out => timer_interrupt |
); |
|
csr_read_address <= id_csr_address when stall_ex = '0' else csr_read_address_p; |
|
store_previous_csr_addr: process(clk, stall_ex) |
begin |
if rising_edge(clk) and stall_ex = '0' then |
299,6 → 307,8
stall => stall_ex, |
flush => flush_ex, |
irq => irq, |
software_interrupt => software_interrupt, |
timer_interrupt => timer_interrupt, |
dmem_address => ex_dmem_address, |
dmem_data_size => ex_dmem_data_size, |
dmem_data_out => ex_dmem_data_out, |
337,9 → 347,11
mem_size_out => ex_mem_size, |
count_instruction_in => id_count_instruction, |
count_instruction_out => ex_count_instruction, |
status_in => status, |
evec_in => evec, |
evec_out => exception_target, |
ie_in => ie, |
ie1_in => ie1, |
mie_in => mie, |
mtvec_in => mtvec, |
mtvec_out => exception_target, |
decode_exception_in => id_exception, |
decode_exception_cause_in => id_exception_cause, |
exception_out => exception_taken, |
/new-privileged-isa/src/pp_fetch.vhd
11,7 → 11,7
--! @brief Instruction fetch unit. |
entity pp_fetch is |
generic( |
RESET_ADDRESS : std_logic_vector(31 downto 0) := x"00000000" |
RESET_ADDRESS : std_logic_vector(31 downto 0) |
); |
port( |
clk : in std_logic; |
/new-privileged-isa/testbenches/tb_processor.vhd
27,6 → 27,10
signal clk : std_logic := '0'; |
constant clk_period : time := 10 ns; |
|
-- Timer clock signal: |
signal timer_clk : std_logic := '0'; |
constant timer_clk_period : time := 100 ns; |
|
-- Common inputs: |
signal reset : std_logic := '1'; |
|
77,7 → 81,7
) port map( |
clk => clk, |
reset => reset, |
timer_clk => clk, |
timer_clk => timer_clk, |
imem_address => imem_address, |
imem_data_in => imem_data_in, |
imem_req => imem_req, |
109,6 → 113,18
end if; |
end process clock; |
|
timer_clock: process |
begin |
timer_clk <= '0'; |
wait for timer_clk_period / 2; |
timer_clk <= '1'; |
wait for timer_clk_period / 2; |
|
if simulation_finished then |
wait; |
end if; |
end process timer_clock; |
|
--! Initializes the instruction memory from file. |
imem_init: process |
file imem_file : text open READ_MODE is IMEM_FILENAME; |
/new-privileged-isa/testbenches/tb_soc.vhd
29,6 → 29,9
signal clk : std_logic; |
constant clk_period : time := 10 ns; |
|
signal timer_clk : std_logic; |
constant timer_clk_period : time := 100 ns; |
|
-- Reset: |
signal reset : std_logic := '1'; |
|
204,17 → 207,18
variable input_value : std_logic_vector(31 downto 0); |
variable temp : std_logic_vector(31 downto 0); |
|
constant DMEM_START : natural := IMEM_SIZE; |
constant DMEM_START_ADDR : natural := IMEM_SIZE; |
begin |
if not initialized then |
-- Read the instruction memory file: |
for i in to_integer(unsigned(IMEM_START_ADDR)) to IMEM_SIZE loop |
for i in 0 to (IMEM_SIZE / 4) - 1 loop |
exit when endfile(imem_file); |
|
readline(imem_file, input_line); |
hread(input_line, input_value); |
|
init_adr_out <= std_logic_vector(to_unsigned(i * 4, init_adr_out'length)); |
init_adr_out <= std_logic_vector(to_unsigned(to_integer(unsigned(IMEM_START_ADDR)) + (i * 4), |
init_adr_out'length)); |
init_dat_out <= input_value; |
init_cyc_out <= '1'; |
init_stb_out <= '1'; |
230,13 → 234,12
wait for clk_period; |
|
-- Read the data memory file: |
for i in 0 to DMEM_SIZE loop |
for i in 0 to (DMEM_SIZE / 4) - 1 loop |
exit when endfile(dmem_file); |
|
readline(dmem_file, input_line); |
hread(input_line, input_value); |
|
|
-- Swap endianness, TODO: prevent this, fix scripts/extract_hex.sh |
temp(7 downto 0) := input_value(31 downto 24); |
temp(15 downto 8) := input_value(23 downto 16); |
245,7 → 248,7
|
input_value := temp; |
|
init_adr_out <= std_logic_vector(to_unsigned(DMEM_START + (i * 4), init_adr_out'length)); |
init_adr_out <= std_logic_vector(to_unsigned(DMEM_START_ADDR + (i * 4), init_adr_out'length)); |
init_dat_out <= input_value; |
init_cyc_out <= '1'; |
init_stb_out <= '1'; |
277,6 → 280,18
end if; |
end process clock; |
|
timer_clock: process |
begin |
timer_clk <= '1'; |
wait for timer_clk_period / 2; |
timer_clk <= '0'; |
wait for timer_clk_period / 2; |
|
if simulation_finished then |
wait; |
end if; |
end process timer_clock; |
|
stimulus: process |
begin |
wait for clk_period * 2; |