mirror of
https://github.com/lowRISC/ibex.git
synced 2025-06-27 17:00:41 -04:00
368 lines
9.6 KiB
Systemverilog
368 lines
9.6 KiB
Systemverilog
// Copyright lowRISC contributors.
|
|
// Copyright 2024 University of Oxford, see also CREDITS.md.
|
|
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
|
// Original author: Louis-Emile Ploix
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
/*
|
|
This module contains the actual instance of the specification. It's quite ugly. Mostly it's just forwarding things to
|
|
different names and ignoring registers we don't care about.
|
|
*/
|
|
|
|
typedef struct packed {
|
|
logic mie;
|
|
logic mpie;
|
|
logic tw;
|
|
logic mprv;
|
|
logic [1:0] mpp;
|
|
} mstatus_t;
|
|
|
|
module spec_api #(
|
|
parameter int unsigned NREGS = 32,
|
|
parameter int unsigned PMPNumRegions = 4
|
|
) (
|
|
input t_MainMode main_mode,
|
|
|
|
output logic rx_a_en_o,
|
|
output logic [4:0] rx_a_addr_o,
|
|
input logic [31:0] rx_a_i,
|
|
output logic rx_b_en_o,
|
|
output logic [4:0] rx_b_addr_o,
|
|
input logic [31:0] rx_b_i,
|
|
|
|
output logic wx_en_o,
|
|
output logic [31:0] wx_o,
|
|
output logic [4:0] wx_addr_o,
|
|
|
|
input logic [31:0] nextpc_i,
|
|
input logic [31:0] pc_i,
|
|
output logic [31:0] pc_o,
|
|
|
|
input logic [31:0] misa_i,
|
|
input logic [31:0] mip_i,
|
|
|
|
input logic [31:0] mvendor_id_i,
|
|
input logic [31:0] march_id_i,
|
|
input logic [31:0] mimp_id_i,
|
|
input logic [31:0] mhart_id_i,
|
|
input logic [31:0] mconfigptr_i,
|
|
|
|
input logic [31:0] mseccfg_i,
|
|
output logic [31:0] mseccfg_o,
|
|
input logic [7:0] pmp_cfg_i[PMPNumRegions],
|
|
output logic [7:0] pmp_cfg_o[PMPNumRegions],
|
|
input logic [31:0] pmp_addr_i[PMPNumRegions],
|
|
output logic [31:0] pmp_addr_o[PMPNumRegions],
|
|
|
|
input logic [31:0] mie_i,
|
|
output logic [31:0] mie_o,
|
|
input t_Privilege priv_i,
|
|
output t_Privilege priv_o,
|
|
input mstatus_t mstatus_i,
|
|
output mstatus_t mstatus_o,
|
|
input logic [31:0] mcause_i,
|
|
output logic [31:0] mcause_o,
|
|
input logic [63:0] mcycle_i,
|
|
output logic [63:0] mcycle_o,
|
|
input logic [31:0] mtval_i,
|
|
output logic [31:0] mtval_o,
|
|
input logic [31:0] mtvec_i,
|
|
output logic [31:0] mtvec_o,
|
|
input logic [31:0] mscratch_i,
|
|
output logic [31:0] mscratch_o,
|
|
input logic [31:0] mepc_i,
|
|
output logic [31:0] mepc_o,
|
|
input logic [31:0] mshwmb_i,
|
|
output logic [31:0] mshwmb_o,
|
|
input logic [31:0] mshwm_i,
|
|
output logic [31:0] mshwm_o,
|
|
input logic [31:0] mcounteren_i,
|
|
output logic [31:0] mcounteren_o,
|
|
|
|
input logic [31:0] insn_bits,
|
|
output logic int_err_o,
|
|
|
|
output logic mem_read_o,
|
|
output logic mem_read_snd_gran_o,
|
|
output logic[31:0] mem_read_fst_addr_o,
|
|
output logic[31:0] mem_read_snd_addr_o,
|
|
input logic[31:0] mem_read_fst_rdata_i,
|
|
input logic[31:0] mem_read_snd_rdata_i,
|
|
|
|
output logic mem_write_o,
|
|
output logic mem_write_snd_gran_o,
|
|
output logic[31:0] mem_write_fst_addr_o,
|
|
output logic[31:0] mem_write_snd_addr_o,
|
|
output logic[31:0] mem_write_fst_wdata_o,
|
|
output logic[31:0] mem_write_snd_wdata_o,
|
|
output logic [3:0] mem_write_fst_be_o,
|
|
output logic [3:0] mem_write_snd_be_o
|
|
);
|
|
|
|
bit rX_sail_invoke[2];
|
|
logic [31:0] rX_sail_invoke_ret[2];
|
|
logic [63:0] rX_sail_invoke_arg_0[2];
|
|
assign rx_a_en_o = rX_sail_invoke[0];
|
|
assign rx_a_addr_o = rX_sail_invoke_arg_0[0][4:0];
|
|
assign rX_sail_invoke_ret[0] = rx_a_i;
|
|
assign rx_b_en_o = rX_sail_invoke[1];
|
|
assign rx_b_addr_o = rX_sail_invoke_arg_0[1][4:0];
|
|
assign rX_sail_invoke_ret[1] = rx_b_i;
|
|
|
|
logic wX_sail_invoke[1];
|
|
logic [63:0] wX_sail_invoke_arg_0[1];
|
|
logic [31:0] wX_sail_invoke_arg_1[1];
|
|
assign wx_en_o = wX_sail_invoke[0];
|
|
assign wx_addr_o = wX_sail_invoke_arg_0[0][4:0];
|
|
assign wx_o = wX_sail_invoke_arg_1[0];
|
|
|
|
logic write_ram_sail_invoke[2];
|
|
logic [31:0] write_ram_sail_invoke_arg_1[2];
|
|
logic [31:0] write_ram_sail_invoke_arg_2[2];
|
|
logic [3:0] write_ram_sail_invoke_arg_3[2];
|
|
assign mem_write_o = write_ram_sail_invoke[0];
|
|
assign mem_write_snd_gran_o = write_ram_sail_invoke[1];
|
|
assign mem_write_fst_addr_o = write_ram_sail_invoke_arg_1[0];
|
|
assign mem_write_snd_addr_o = write_ram_sail_invoke_arg_1[1];
|
|
assign mem_write_fst_wdata_o = write_ram_sail_invoke_arg_2[0];
|
|
assign mem_write_snd_wdata_o = write_ram_sail_invoke_arg_2[1];
|
|
assign mem_write_fst_be_o = write_ram_sail_invoke_arg_3[0];
|
|
assign mem_write_snd_be_o = write_ram_sail_invoke_arg_3[1];
|
|
|
|
logic read_ram_sail_invoke[2];
|
|
logic [31:0] read_ram_sail_invoke_ret[2];
|
|
logic [31:0] read_ram_sail_invoke_arg_1[2];
|
|
assign mem_read_o = read_ram_sail_invoke[0];
|
|
assign mem_read_snd_gran_o = read_ram_sail_invoke[1];
|
|
assign mem_read_fst_addr_o = read_ram_sail_invoke_arg_1[0];
|
|
assign mem_read_snd_addr_o = read_ram_sail_invoke_arg_1[1];
|
|
assign read_ram_sail_invoke_ret[0] = mem_read_fst_rdata_i;
|
|
assign read_ram_sail_invoke_ret[1] = mem_read_snd_rdata_i;
|
|
|
|
t_MainResult main_result;
|
|
|
|
t_Mstatus mstatus_out;
|
|
assign mstatus_o.mie = mstatus_out.bits[3];
|
|
assign mstatus_o.mpie = mstatus_out.bits[7];
|
|
assign mstatus_o.tw = mstatus_out.bits[21];
|
|
assign mstatus_o.mprv = mstatus_out.bits[17];
|
|
assign mstatus_o.mpp = mstatus_out.bits[12:11];
|
|
|
|
t_Mcause mcause_out;
|
|
assign mcause_o = mcause_out.bits;
|
|
|
|
t_Minterrupts mie_out;
|
|
assign mie_o = mie_out.bits;
|
|
|
|
t_Counteren mcounteren_out;
|
|
assign mcounteren_o = mcounteren_out.bits;
|
|
|
|
t_Mtvec mtvec_out;
|
|
assign mtvec_o = mtvec_out.bits;
|
|
|
|
t_Pmpcfg_ent pmpcfg_n_in[64];
|
|
logic [31:0] pmpaddr_n_in[64];
|
|
t_Pmpcfg_ent pmpcfg_n_out[64];
|
|
logic [31:0] pmpaddr_n_out[64];
|
|
for (genvar i = 0; i < 64; i++) begin: g_pmp_bind
|
|
if (i < PMPNumRegions) begin: g_pmp_bind_real
|
|
assign pmpcfg_n_in[i] = '{bits: pmp_cfg_i[i]};
|
|
assign pmpaddr_n_in[i] = pmp_addr_i[i];
|
|
|
|
assign pmp_cfg_o[i] = pmpcfg_n_out[i].bits[7:0];
|
|
assign pmp_addr_o[i] = pmpaddr_n_out[i];
|
|
end else begin: g_pmp_bind_zero
|
|
// These shouldn't ever be used anyway
|
|
assign pmpcfg_n_in[i] = '{bits: 0};
|
|
assign pmpaddr_n_in[i] = 0;
|
|
end
|
|
end
|
|
|
|
t_Mseccfg_ent mseccfg_out;
|
|
assign mseccfg_o = mseccfg_out.bits;
|
|
|
|
sail_ibexspec spec_i(
|
|
.cur_inst_in(insn_bits),
|
|
.cur_inst_out(),
|
|
.cur_privilege_in(priv_i),
|
|
.cur_privilege_out(priv_o),
|
|
.instbits_in(insn_bits),
|
|
.instbits_out(),
|
|
.marchid_in(march_id_i),
|
|
.marchid_out(),
|
|
.mcause_in('{bits: mcause_i}),
|
|
.mcause_out,
|
|
.mconfigptr_in(mconfigptr_i),
|
|
.mconfigptr_out(),
|
|
.mcounteren_in('{ bits: mcounteren_i }),
|
|
.mcounteren_out,
|
|
.mcountinhibit_in(),
|
|
.mcountinhibit_out(),
|
|
.mcycle_in(mcycle_i),
|
|
.mcycle_out(mcycle_o),
|
|
.medeleg_in('{bits: 32'h0}),
|
|
.medeleg_out(),
|
|
.menvcfg_in('{bits: 32'h0}),
|
|
.menvcfg_out(),
|
|
.mepc_in(mepc_i),
|
|
.mepc_out(mepc_o),
|
|
.mhartid_in(mhart_id_i),
|
|
.mhartid_out(mhart_id_o),
|
|
.mideleg_in(),
|
|
.mideleg_out(),
|
|
.mie_in('{bits: mie_i}),
|
|
.mie_out,
|
|
.mimpid_in(mimp_id_i),
|
|
.mimpid_out(mimp_id_o),
|
|
.minstret_in(minstret_i),
|
|
.minstret_out(minstret_o),
|
|
.minstret_increment_in(),
|
|
.minstret_increment_out(),
|
|
.mip_in('{bits: mip_i}),
|
|
.mip_out(),
|
|
.misa_in('{bits: misa_i}),
|
|
.misa_out(),
|
|
.mscratch_in(mscratch_i),
|
|
.mscratch_out(mscratch_o),
|
|
.mstatus_in('{bits:
|
|
(32'(mstatus_i.mie) << 3) |
|
|
(32'(mstatus_i.mpie) << 7) |
|
|
(32'(mstatus_i.tw) << 21) |
|
|
(32'(mstatus_i.mprv) << 17) |
|
|
(32'(mstatus_i.mpp) << 11)
|
|
}),
|
|
.mstatus_out,
|
|
.mstatush_in('{bits: 32'b0}),
|
|
.mstatush_out(),
|
|
.mtval_in(mtval_i),
|
|
.mtval_out(mtval_o),
|
|
.mtvec_in('{bits: mtvec_i}),
|
|
.mtvec_out,
|
|
.mvendorid_in(mvendor_id_i),
|
|
.mvendorid_out(mvendor_id_o),
|
|
.nextPC_in(nextpc_i),
|
|
.nextPC_out(pc_o),
|
|
.PC_in(pc_i),
|
|
.PC_out(),
|
|
.mseccfg_in('{bits: mseccfg_i}),
|
|
.mseccfg_out,
|
|
.mseccfgh_in(32'h0),
|
|
.mseccfgh_out(),
|
|
.pmpaddr_n_in,
|
|
.pmpaddr_n_out,
|
|
.pmpcfg_n_in,
|
|
.pmpcfg_n_out,
|
|
.scause_in(),
|
|
.scause_out(),
|
|
.scounteren_in(),
|
|
.scounteren_out(),
|
|
.sedeleg_in(),
|
|
.sedeleg_out(),
|
|
.senvcfg_in(),
|
|
.senvcfg_out(),
|
|
.sepc_in(),
|
|
.sepc_out(),
|
|
.sideleg_in(),
|
|
.sideleg_out(),
|
|
.sscratch_in(),
|
|
.sscratch_out(),
|
|
.stval_in(),
|
|
.stval_out(),
|
|
.stvec_in(),
|
|
.stvec_out(),
|
|
.tselect_in(),
|
|
.tselect_out(),
|
|
.x1_in(),
|
|
.x1_out(),
|
|
.x2_in(),
|
|
.x2_out(),
|
|
.x3_in(),
|
|
.x3_out(),
|
|
.x4_in(),
|
|
.x4_out(),
|
|
.x5_in(),
|
|
.x5_out(),
|
|
.x6_in(),
|
|
.x6_out(),
|
|
.x7_in(),
|
|
.x7_out(),
|
|
.x8_in(),
|
|
.x8_out(),
|
|
.x9_in(),
|
|
.x9_out(),
|
|
.x10_in(),
|
|
.x10_out(),
|
|
.x11_in(),
|
|
.x11_out(),
|
|
.x12_in(),
|
|
.x12_out(),
|
|
.x13_in(),
|
|
.x13_out(),
|
|
.x14_in(),
|
|
.x14_out(),
|
|
.x15_in(),
|
|
.x15_out(),
|
|
.x16_in(),
|
|
.x16_out(),
|
|
.x17_in(),
|
|
.x17_out(),
|
|
.x18_in(),
|
|
.x18_out(),
|
|
.x19_in(),
|
|
.x19_out(),
|
|
.x20_in(),
|
|
.x20_out(),
|
|
.x21_in(),
|
|
.x21_out(),
|
|
.x22_in(),
|
|
.x22_out(),
|
|
.x23_in(),
|
|
.x23_out(),
|
|
.x24_in(),
|
|
.x24_out(),
|
|
.x25_in(),
|
|
.x25_out(),
|
|
.x26_in(),
|
|
.x26_out(),
|
|
.x27_in(),
|
|
.x27_out(),
|
|
.x28_in(),
|
|
.x28_out(),
|
|
.x29_in(),
|
|
.x29_out(),
|
|
.x30_in(),
|
|
.x30_out(),
|
|
.x31_in(),
|
|
.x31_out(),
|
|
|
|
.wX_sail_invoke,
|
|
.wX_sail_invoke_ret(),
|
|
.wX_sail_invoke_arg_0,
|
|
.wX_sail_invoke_arg_1,
|
|
|
|
.rX_sail_invoke,
|
|
.rX_sail_invoke_ret,
|
|
.rX_sail_invoke_arg_0,
|
|
|
|
.write_ram_sail_invoke,
|
|
.write_ram_sail_invoke_ret(),
|
|
.write_ram_sail_invoke_arg_0(),
|
|
.write_ram_sail_invoke_arg_1,
|
|
.write_ram_sail_invoke_arg_2,
|
|
.write_ram_sail_invoke_arg_3,
|
|
|
|
.read_ram_sail_invoke,
|
|
.read_ram_sail_invoke_ret,
|
|
.read_ram_sail_invoke_arg_0(),
|
|
.read_ram_sail_invoke_arg_1,
|
|
|
|
.main_result(main_result),
|
|
.insn_bits(insn_bits),
|
|
.mode(main_mode)
|
|
);
|
|
|
|
assign int_err_o = spec_i.sail_reached_unreachable |
|
|
spec_i.sail_have_exception |
|
|
(main_result != MAINRES_OK);
|
|
|
|
endmodule
|