// Copyright (c) 2013-2019 Bluespec, Inc. All Rights Reserved // //- // RVFI_DII + CHERI modifications: // Copyright (c) 2020 Alexandre Joannou // Copyright (c) 2020 Peter Rugg // Copyright (c) 2020 Jonathan Woodruff // All rights reserved. // // This software was developed by SRI International and the University of // Cambridge Computer Laboratory (Department of Computer Science and // Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the // DARPA SSITH research programme. // // This work was supported by NCSC programme grant 4212611/RFA 15971 ("SafeBet"). //- package SoC_Map; // ================================================================ // This module defines the overall 'address map' of the SoC, showing // the addresses serviced by each slave IP, and which addresses are // memory vs. I/O. // ***** WARNING! WARNING! WARNING! ***** // During system integration, this address map should be identical to // the system interconnect settings (e.g., routing of requests between // masters and slaves). This map is also needed by software so that // it knows how to address various IPs. // This module contains no state; it just has constants, and so can be // freely instantiated at multiple places in the SoC module hierarchy // at no hardware cost. It allows this map to be defined in one // place and shared across the SoC. // ================================================================ // Exports export SoC_Map_Struct (..), soc_map_struct; export SoC_Map_IFC (..), mkSoC_Map; export Num_Masters; export imem_master_num; export dmem_master_num; export Num_Slaves; export Wd_SId; export boot_rom_slave_num; export mem0_controller_slave_num; export uart0_slave_num; export N_External_Interrupt_Sources; export n_external_interrupt_sources; export irq_num_uart0; // ================================================================ // Bluespec library imports import Routable :: *; // For Range // ================================================================ // Project imports import Fabric_Defs :: *; // Only for type Fabric_Addr // ================================================================ // Top-level-struct version of the SoC Map for RISCY-OOO typedef struct { Bit #(64) near_mem_io_addr_base; Bit #(64) main_mem_addr_base; Bit #(64) main_mem_addr_size; Bit #(64) pc_reset_value; } SoC_Map_Struct deriving (FShow); SoC_Map_Struct soc_map_struct = SoC_Map_Struct { near_mem_io_addr_base: 'h_0200_0000, main_mem_addr_base: 'h_8000_0000, `ifdef RVFI_DII main_mem_addr_size: 'h_4000_0000, pc_reset_value: 'h_8000_0000 `else main_mem_addr_size: 'h_1000_0000, pc_reset_value: 'h_0000_1000 `endif }; // ================================================================ // Interface and module for the address map interface SoC_Map_IFC; (* always_ready *) method Range#(Wd_Addr) m_near_mem_io_addr_range; (* always_ready *) method Range#(Wd_Addr) m_plic_addr_range; (* always_ready *) method Range#(Wd_Addr) m_uart0_addr_range; (* always_ready *) method Range#(Wd_Addr) m_boot_rom_addr_range; (* always_ready *) method Range#(Wd_Addr) m_mem0_controller_addr_range; (* always_ready *) method Range#(Wd_Addr) m_tcm_addr_range; (* always_ready *) method Bool m_is_mem_addr (Fabric_Addr addr); (* always_ready *) method Bool m_is_IO_addr (Fabric_Addr addr, Bool imem_not_dmem); (* always_ready *) method Bool m_is_near_mem_IO_addr (Fabric_Addr addr); (* always_ready *) method Bit #(64) m_pc_reset_value; (* always_ready *) method Bit #(64) m_mtvec_reset_value; (* always_ready *) method Bit #(64) m_nmivec_reset_value; endinterface // ================================================================ (* synthesize *) module mkSoC_Map (SoC_Map_IFC); // ---------------------------------------------------------------- // Near_Mem_IO (including CLINT, the core-local interruptor) let near_mem_io_addr_range = Range { base: 'h_0200_0000, size: 'h_0000_C000 // 48K }; // ---------------------------------------------------------------- // PLIC let plic_addr_range = Range { base: 'h0C00_0000, size: 'h0040_0000 // 4M }; // ---------------------------------------------------------------- // UART 0 let uart0_addr_range = Range { base: 'hC000_0000, size: 'h0000_0080 // 128 }; // ---------------------------------------------------------------- // Boot ROM let boot_rom_addr_range = Range { base: 'h_0000_1000, size: 'h_0000_1000 // 4K }; // ---------------------------------------------------------------- // Main Mem Controller 0 let mem0_controller_addr_range = Range { base: 'h_8000_0000, size: 'h_4000_0000 // 1 GB }; // ---------------------------------------------------------------- // Tightly-coupled memory ('TCM'; optional) `ifdef Near_Mem_TCM // Integer kB_per_TCM = 'h4; // 4KB // Integer kB_per_TCM = 'h40; // 64KB // Integer kB_per_TCM = 'h80; // 128KB // Integer kB_per_TCM = 'h400; // 1 MB Integer kB_per_TCM = 'h4000; // 16 MB `else Integer kB_per_TCM = 0; `endif Integer bytes_per_TCM = kB_per_TCM * 'h400; let tcm_addr_range = Range { base: 'h_0000_0000, size: fromInteger (bytes_per_TCM) }; // ---------------------------------------------------------------- // Memory address predicate // Identifies memory addresses in the Fabric. // (Caches need this information to cache these addresses.) function Bool fn_is_mem_addr (Fabric_Addr addr); return ( inRange(mem0_controller_addr_range, addr) || inRange(tcm_addr_range, addr)); endfunction // ---------------------------------------------------------------- // I/O address predicate // Identifies I/O addresses in the Fabric. // (Caches need this information to avoid cacheing these addresses.) function Bool fn_is_IO_addr (Fabric_Addr addr, Bool imem_not_dmem); return ( inRange(boot_rom_addr_range, addr) || ( (! imem_not_dmem) && ( inRange(near_mem_io_addr_range, addr) || inRange(plic_addr_range, addr) || inRange(uart0_addr_range, addr) ) ) ); endfunction // ---------------------------------------------------------------- // PC, MTVEC and NMIVEC reset values Bit #(64) pc_reset_value = rangeBase(boot_rom_addr_range); Bit #(64) mtvec_reset_value = 'h1000; // TODO Bit #(64) nmivec_reset_value = ?; // TODO // ================================================================ // INTERFACE method Range#(Wd_Addr) m_near_mem_io_addr_range = near_mem_io_addr_range; method Range#(Wd_Addr) m_plic_addr_range = plic_addr_range; method Range#(Wd_Addr) m_uart0_addr_range = uart0_addr_range; method Range#(Wd_Addr) m_boot_rom_addr_range = boot_rom_addr_range; method Range#(Wd_Addr) m_mem0_controller_addr_range = mem0_controller_addr_range; method Range#(Wd_Addr) m_tcm_addr_range = tcm_addr_range; method Bool m_is_mem_addr (Fabric_Addr addr) = fn_is_mem_addr (addr); method Bool m_is_IO_addr (Fabric_Addr addr, Bool imem_not_dmem) = fn_is_IO_addr (addr, imem_not_dmem); method Bool m_is_near_mem_IO_addr (Fabric_Addr addr) = inRange (near_mem_io_addr_range, addr); method Bit #(64) m_pc_reset_value = pc_reset_value; method Bit #(64) m_mtvec_reset_value = mtvec_reset_value; method Bit #(64) m_nmivec_reset_value = nmivec_reset_value; endmodule // ================================================================ // Count and master-numbers of masters in the fabric. typedef 2 Num_Masters; Integer imem_master_num = 0; Integer dmem_master_num = 1; // ================================================================ // Count and slave-numbers of slaves in the fabric. typedef 3 Num_Slaves; Integer boot_rom_slave_num = 0; Integer mem0_controller_slave_num = 1; Integer uart0_slave_num = 2; // ================================================================ // Width of fabric 'id' buses typedef TAdd#(TAdd#(Wd_MId, TLog#(Num_Masters)),1) Wd_SId; // ================================================================ // Interrupt request numbers (== index in to vector of // interrupt-request lines in Core) typedef 16 N_External_Interrupt_Sources; Integer n_external_interrupt_sources = valueOf (N_External_Interrupt_Sources); Integer irq_num_uart0 = 0; // ================================================================ endpackage