diff --git a/fast-models-examples/STM_Demo/Model/FVP_STM/Build_Cortex-A57/FVP_STM_Cortex-A57.sgproj b/fast-models-examples/STM_Demo/Model/FVP_STM/Build_Cortex-A57/FVP_STM_Cortex-A57.sgproj new file mode 100644 index 00000000..b8314fa6 --- /dev/null +++ b/fast-models-examples/STM_Demo/Model/FVP_STM/Build_Cortex-A57/FVP_STM_Cortex-A57.sgproj @@ -0,0 +1,193 @@ +# This file is autogenerated by FastSim/BuildSGProjs.py. Please do not edit directly. +sgproject "FVP_STM_Cortex-A57.sgproj" +{ + TOP_LEVEL_COMPONENT = "FVP_STM"; + ACTIVE_CONFIG_LINUX = "Linux64-Release-GCC-4.9"; + ACTIVE_CONFIG_LINUX_ARMV8L = "Linux64_armv8l-Release-GCC-6.3"; + ACTIVE_CONFIG_WINDOWS = "Win64-Release-VC2015"; + config "Linux64-Debug-GCC-4.9" + { + ADDITIONAL_COMPILER_SETTINGS = "-march=core2 -ggdb3 -Wall -std=c++11"; + ADDITIONAL_LINKER_SETTINGS = "-Wl,--no-undefined"; + BUILD_DIR = "./Linux64-Debug-GCC-4.9"; + COMPILER = "gcc-4.9"; + CONFIG_DESCRIPTION = "Default x86_64 Linux configuration for GCC 4.9 with debug information"; + CONFIG_NAME = "Linux64-Debug-GCC-4.9"; + ENABLE_DEBUG_SUPPORT = "1"; + PLATFORM = "Linux64"; + SIMGEN_COMMAND_LINE = "--num-comps-file 10"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + config "Linux64-Release-GCC-4.9" + { + ADDITIONAL_COMPILER_SETTINGS = "-march=core2 -O3 -Wall -std=c++11"; + ADDITIONAL_LINKER_SETTINGS = "-Wl,--no-undefined"; + BUILD_DIR = "./Linux64-Release-GCC-4.9"; + COMPILER = "gcc-4.9"; + CONFIG_DESCRIPTION = "Default x86_64 Linux configuration for GCC 4.9, optimized for speed"; + CONFIG_NAME = "Linux64-Release-GCC-4.9"; + PLATFORM = "Linux64"; + PREPROCESSOR_DEFINES = "NDEBUG"; + SIMGEN_COMMAND_LINE = "--num-comps-file 50"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + config "Linux64-Debug-GCC-6.4" + { + ADDITIONAL_COMPILER_SETTINGS = "-march=core2 -ggdb3 -Wall -std=c++11 -Wno-deprecated -Wno-unused-function"; + ADDITIONAL_LINKER_SETTINGS = "-Wl,--no-undefined"; + BUILD_DIR = "./Linux64-Debug-GCC-6.4"; + COMPILER = "gcc-6.4"; + CONFIG_DESCRIPTION = "Default x86_64 Linux configuration for GCC 6.4 with debug information"; + CONFIG_NAME = "Linux64-Debug-GCC-6.4"; + ENABLE_DEBUG_SUPPORT = "1"; + PLATFORM = "Linux64"; + SIMGEN_COMMAND_LINE = "--num-comps-file 10"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + config "Linux64-Release-GCC-6.4" + { + ADDITIONAL_COMPILER_SETTINGS = "-march=core2 -O3 -Wall -std=c++11 -Wno-deprecated -Wno-unused-function"; + ADDITIONAL_LINKER_SETTINGS = "-Wl,--no-undefined"; + BUILD_DIR = "./Linux64-Release-GCC-6.4"; + COMPILER = "gcc-6.4"; + CONFIG_DESCRIPTION = "Default x86_64 Linux configuration for GCC 6.4, optimized for speed"; + CONFIG_NAME = "Linux64-Release-GCC-6.4"; + PLATFORM = "Linux64"; + PREPROCESSOR_DEFINES = "NDEBUG"; + SIMGEN_COMMAND_LINE = "--num-comps-file 50"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + config "Linux64-Debug-GCC-7.3" + { + ADDITIONAL_COMPILER_SETTINGS = "-march=core2 -ggdb3 -Wall -std=c++11 -Wno-deprecated -Wno-unused-function"; + ADDITIONAL_LINKER_SETTINGS = "-Wl,--no-undefined"; + BUILD_DIR = "./Linux64-Debug-GCC-7.3"; + COMPILER = "gcc-7.3"; + CONFIG_DESCRIPTION = "Default x86_64 Linux configuration for GCC 7.3 with debug information"; + CONFIG_NAME = "Linux64-Debug-GCC-7.3"; + ENABLE_DEBUG_SUPPORT = "1"; + PLATFORM = "Linux64"; + SIMGEN_COMMAND_LINE = "--num-comps-file 10"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + config "Linux64-Release-GCC-7.3" + { + ADDITIONAL_COMPILER_SETTINGS = "-march=core2 -O3 -Wall -std=c++11 -Wno-deprecated -Wno-unused-function"; + ADDITIONAL_LINKER_SETTINGS = "-Wl,--no-undefined"; + BUILD_DIR = "./Linux64-Release-GCC-7.3"; + COMPILER = "gcc-7.3"; + CONFIG_DESCRIPTION = "Default x86_64 Linux configuration for GCC 7.3, optimized for speed"; + CONFIG_NAME = "Linux64-Release-GCC-7.3"; + PLATFORM = "Linux64"; + PREPROCESSOR_DEFINES = "NDEBUG"; + SIMGEN_COMMAND_LINE = "--num-comps-file 50"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + config "Linux64_armv8l-Debug-GCC-6.3" + { + ADDITIONAL_COMPILER_SETTINGS = "-march=armv8-a -ggdb3 -Wall -std=c++11 -Wno-deprecated -Wno-unused-function"; + ADDITIONAL_LINKER_SETTINGS = "-Wl,--no-undefined"; + BUILD_DIR = "./Linux64_armv8l-Debug-GCC-6.3"; + COMPILER = "gcc-6.3"; + CONFIG_DESCRIPTION = "Default armv8l Linux configuration for GCC 6.3 with debug information"; + CONFIG_NAME = "Linux64_armv8l-Debug-GCC-6.3"; + ENABLE_DEBUG_SUPPORT = "1"; + PLATFORM = "Linux64_armv8l"; + SIMGEN_COMMAND_LINE = "--num-comps-file 10"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + config "Linux64_armv8l-Release-GCC-6.3" + { + ADDITIONAL_COMPILER_SETTINGS = "-march=armv8-a -O3 -fomit-frame-pointer -Wall -std=c++11 -Wno-deprecated -Wno-unused-function"; + ADDITIONAL_LINKER_SETTINGS = "-Wl,--no-undefined"; + BUILD_DIR = "./Linux64_armv8l-Release-GCC-6.3"; + COMPILER = "gcc-6.3"; + CONFIG_DESCRIPTION = "Default armv8l Linux configuration for GCC 6.3, optimized for speed"; + CONFIG_NAME = "Linux64_armv8l-Release-GCC-6.3"; + PLATFORM = "Linux64_armv8l"; + PREPROCESSOR_DEFINES = "NDEBUG"; + SIMGEN_COMMAND_LINE = "--num-comps-file 50"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + config "Win64-Debug-VC2015" + { + ADDITIONAL_COMPILER_SETTINGS = "/Od /RTCsu /Zi"; + ADDITIONAL_LINKER_SETTINGS = "/DEBUG"; + BUILD_DIR = "./Win64-Debug-VC2015"; + COMPILER = "VC2015"; + CONFIG_DESCRIPTION = "Default x86_64 Windows configuration for Visual Studio 2015 with debug information"; + CONFIG_NAME = "Win64-Debug-VC2015"; + ENABLE_DEBUG_SUPPORT = "1"; + PLATFORM = "Win64D"; + SIMGEN_COMMAND_LINE = "--num-comps-file 10"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + config "Win64-Release-VC2015" + { + ADDITIONAL_COMPILER_SETTINGS = "/O2"; + BUILD_DIR = "./Win64-Release-VC2015"; + COMPILER = "VC2015"; + CONFIG_DESCRIPTION = "Default x86_64 Windows configuration for Visual Studio 2015, optimized for speed"; + CONFIG_NAME = "Win64-Release-VC2015"; + PLATFORM = "Win64"; + PREPROCESSOR_DEFINES = "NDEBUG"; + SIMGEN_COMMAND_LINE = "--num-comps-file 50"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + config "Win64-Debug-VC2017" + { + ADDITIONAL_COMPILER_SETTINGS = "/Od /RTCsu /Zi"; + ADDITIONAL_LINKER_SETTINGS = "/DEBUG"; + BUILD_DIR = "./Win64-Debug-VC2017"; + COMPILER = "VC2017"; + CONFIG_DESCRIPTION = "Default x86_64 Windows configuration for Visual Studio 2017 with debug information"; + CONFIG_NAME = "Win64-Debug-VC2017"; + ENABLE_DEBUG_SUPPORT = "1"; + PLATFORM = "Win64D"; + SIMGEN_COMMAND_LINE = "--num-comps-file 10"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + config "Win64-Release-VC2017" + { + ADDITIONAL_COMPILER_SETTINGS = "/O2"; + BUILD_DIR = "./Win64-Release-VC2017"; + COMPILER = "VC2017"; + CONFIG_DESCRIPTION = "Default x86_64 Windows configuration for Visual Studio 2017, optimized for speed"; + CONFIG_NAME = "Win64-Release-VC2017"; + PLATFORM = "Win64"; + PREPROCESSOR_DEFINES = "NDEBUG"; + SIMGEN_COMMAND_LINE = "--num-comps-file 50"; + SIMGEN_WARNINGS_AS_ERRORS = "1"; + TARGET_MAXVIEW = "0"; + TARGET_SYSTEMC_ISIM = "1"; + } + files + { + path = "$(PVLIB_HOME)/etc/sglib.sgrepo"; + path = "$PVLIB_HOME/examples/LISA/FVP_MPS2/LISA/CMSDK_UART.lisa"; + path = "../LISA/FVP_STM.lisa"; + path = "../LISA/STM500.lisa"; + } +} diff --git a/fast-models-examples/STM_Demo/Model/FVP_STM/Build_Cortex-A57/build.bat b/fast-models-examples/STM_Demo/Model/FVP_STM/Build_Cortex-A57/build.bat new file mode 100755 index 00000000..d06cf338 --- /dev/null +++ b/fast-models-examples/STM_Demo/Model/FVP_STM/Build_Cortex-A57/build.bat @@ -0,0 +1,9 @@ +@echo off + +rem brief Build a CADI system using simgen +rem +rem Copyright ARM Limited 2020 All Rights Reserved. + +"%MAXCORE_HOME%\bin\simgen" --num-comps-file 50 --gen-sysgen --warnings-as-errors -p "FVP_STM_Cortex-A57.sgproj" -b %* + +rem eof build.bat diff --git a/fast-models-examples/STM_Demo/Model/FVP_STM/Build_Cortex-A57/build.sh b/fast-models-examples/STM_Demo/Model/FVP_STM/Build_Cortex-A57/build.sh new file mode 100755 index 00000000..114e2ed9 --- /dev/null +++ b/fast-models-examples/STM_Demo/Model/FVP_STM/Build_Cortex-A57/build.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# vim: syntax=sh + +# brief Build a CADI system using simgen +# +# Copyright ARM Limited 2020 All Rights Reserved. + +simgen --num-comps-file 50 --gen-sysgen --warnings-as-errors -p "FVP_STM_Cortex-A57.sgproj" -b $* + +# eof build.sh diff --git a/fast-models-examples/STM_Demo/Model/FVP_STM/LISA/FVP_STM.lisa b/fast-models-examples/STM_Demo/Model/FVP_STM/LISA/FVP_STM.lisa new file mode 100644 index 00000000..28b1d5da --- /dev/null +++ b/fast-models-examples/STM_Demo/Model/FVP_STM/LISA/FVP_STM.lisa @@ -0,0 +1,60 @@ +component FVP_STM +{ + properties + { + version = "0.0"; + description = "ARM platform for STM"; + } + + includes + { + #define STM_AXI_BASE 0x28000000ULL + #define STM_APB_BASE 0x20100000ULL + #define UART0_BASE 0x40004000 + } + + resources + { + PARAMETER { description("RAM Fill Pattern 1"), default(0x0), type(uint32_t) } ram_fill_pattern_1; + PARAMETER { description("RAM Fill Pattern 2"), default(0x0), type(uint32_t) } ram_fill_pattern_2; + } + + composition + { + ram : RAMDevice(fill1=ram_fill_pattern_1, fill2=ram_fill_pattern_2); + cpu : ARMCortexA57x4CT("PERIPHBASE"=0x2C000000, + "cpu0.semihosting-heap_base".default = 0x00000000, + "cpu0.semihosting-heap_limit".default = 0xff000000, + "cpu0.semihosting-stack_limit".default = 0xff000000, + "cpu0.semihosting-stack_base".default = 0xffff0000); + uart0 : PL011_Uart(revision="r1p5"); + stm : STM500(); + telnetterminal0 : TelnetTerminal(); + busdecoder : PVBusDecoder; + masterclock : MasterClock; + clk100Mhz : ClockDivider("mul"=100000000, "div" =1); + } + + connection + { + // Clock + masterclock.clk_out => clk100Mhz.clk_in; + clk100Mhz.clk_out => cpu.clk_in; + + // RAM + // All transaction go to memory by default + busdecoder.pvbus_m_range[0x00000000..0xffffFFFF] => ram.pvbus; + + // STM + busdecoder.pvbus_m_range[STM_AXI_BASE..STM_AXI_BASE+0x3FFF] => stm.AXI[STM_AXI_BASE..STM_AXI_BASE+0x3FFF]; + busdecoder.pvbus_m_range[STM_APB_BASE..STM_APB_BASE+0x3FFF] => stm.DebugAPB; + + // CPU + cpu.pvbus_m0 => busdecoder.pvbus_s; + + // UART + busdecoder.pvbus_m_range[UART0_BASE..UART0_BASE+0xFFF] => uart0.pvbus; + clk100Mhz.clk_out => uart0.clk_in_ref; + uart0.serial_out => telnetterminal0.serial; + } +} diff --git a/fast-models-examples/STM_Demo/Model/FVP_STM/LISA/STM500.lisa b/fast-models-examples/STM_Demo/Model/FVP_STM/LISA/STM500.lisa new file mode 100644 index 00000000..023fd983 --- /dev/null +++ b/fast-models-examples/STM_Demo/Model/FVP_STM/LISA/STM500.lisa @@ -0,0 +1,827 @@ +/* + * The confidential and proprietary information contained in this file may + * only be used by a person authorised under and to the extent permitted + * by a subsisting licensing agreement from Arm Limited. + * + * Copyright 2020 Arm Limited. + * All rights reserved. + * + * This entire notice must be reproduced on all copies of this file + * and copies of this file may only be made by a person if such person is + * permitted to do so under the terms of a subsisting license agreement + * from Arm Limited. + * + * + */ +component STM500 +{ + properties + { + version = "unreleased"; + component_type = "Peripheral"; + description = "STM 500 Model"; + } + + includes + { + + #include "sg/SGComponentWithSchedulerAccess.h" + + typedef unsigned int STM_RO; + typedef STM_RO STM_RW; + typedef STM_RW STM_NA; + + struct stmAPB { + STM_RW STMSTIMR[32]; + STM_NA RSVD_0[608]; + STM_NA IMPDEF[4][64]; + STM_RW STMSPER; + STM_NA RSVD_2[7]; + STM_RW STMSPTER; + STM_NA RSVD_3[7]; + STM_RW STMPRIVMASKR; + STM_NA RSVD_4[7]; + STM_RW STMSPSCR; + STM_RW STMSPMSCR; + STM_RW STMSPOVERRIDER; + STM_RW STMSPMOVERRIDER; + STM_RW STMSPTRIGCSR; + STM_NA RSVD_5[3]; + STM_RW STMTCSR; + #define STMTCSR_EN (1 << 0) + #define STMTCSR_TSEN (1 << 1) + #define STMTCSR_SYNCEN (1 << 2) + #define STMTCSR_HWTEN (1 << 3) + #define STMTCSR_COMPEN (1 << 5) + #define STMTCSR_BUSY (1 << 23) + STM_RW STMTSSTIMR; + STM_NA RSVD_6; + STM_RW STMTSFREQR; + STM_RW STMSYNCR; + STM_RW STMAUXCR; + STM_NA RSVD_7[2]; + STM_RO STMFEAT1R = {0x006587D1}; + STM_RO STMFEAT2R = {0x000104F2}; + STM_RO STMFEAT3R = {0x0000007F}; + STM_RO RSVD_8[15]; + union { + STM_NA RSVD[6]; + struct STM_IT { + STM_RW STMITTRIGGER; + STM_RW STMITATBDATA0; + STM_RW STMITATBCTR2; + STM_RW STMITATBID; + STM_RW STMITATBCTR0; + STM_NA RSVD; + } STMIT; + } RSVD_9; + STM_RW STMITCTRL; + STM_NA RSVD_A[39]; + STM_RW STMCLAIMSET; + STM_RW STMCLAIMCLR; + STM_NA RSVD_B[2]; + STM_RW STMLAR; + #define STMLAR_UNLOCK (0xc5acce55) + #define STMLAR_LOCK (0x00000000) + STM_RW STMLSR; + #define STMLSR_SLI (1 << 0) + #define STMLSR_SLK (1 << 1) + STM_RW STMAUTHSTATUS = {0x000000AA}; + STM_RO STMDEVARCH = {0x0}; + STM_RO RSVD_C[2] = {0x0,0x0}; + STM_RO STMDEVID = {0x00010000}; + STM_RO STMDEVTYPE = {0x00000063}; + STM_RO STMPIDR[8] = {0x62, 0xB9, 0x1B, 0x00, 0x04, 0x0, 0x0, 0x0}; + STM_RO STMCIDR[4] = {0x0D, 0x90, 0x05, 0xB1}; + }; + + + /* + * Packet : + * https://static.docs.arm.com/ihi0032/b/IHI0032B_amba_atb_protocol_spec.pdf + * 64 bit value + * send_packet() + */ + + /* STPv2 + * Doc : + * 1. MIPI Alliance Specification for System Trace Protocol (STP), version 2.1 + * 2. STPv2 Trace Protocol for ARM CoreSight STMs + * + * + * STPv2: VERSION / MASTER_PACKET / CHANNEL_PACKET / DATA_PACKET / FLAG_PACKET / ERROR_PACKET / NULL_PACKET / FREQ_PACKET / TRIG_PACKET + * The STM-500 only generates STPv2NAT timestamps. + */ + + class STPv2 + { + + private: + + uint64_t data_to_send = {0}; + uint32_t data_completed = {0}; + + uint8_t current_master = {0}; + uint16_t current_channel = {0}; + + template + void add_data(T data, int size) + { + // printf(" data_completed = %d, data_to_send = %lx size = %d data = %lx \n", data_completed, data_to_send, size, (uint64_t )data); + if (size + data_completed > 64 ) + { + int space = 64 - data_completed; + data_to_send |= ((data & ((1ULL<> space; + size = size - space; + } + + data_to_send |= ((data & ((1ULL< + T nibbles_revers(T num) + { + uint64_t const_mask[] = { 0x0F0F0F0F0F0F0F0F + , 0xF0F0F0F0F0F0F0F0 + , 0x00FF00FF00FF00FF + , 0xFF00FF00FF00FF00 + , 0x0000FFFF0000FFFF + , 0xFFFF0000FFFF0000 + , 0x00000000FFFFFFFF + , 0xFFFFFFFF00000000 }; + + int shift = 4; + for (unsigned int i =0; ((unsigned int) (1<>shift); + shift *= 2; + } + return num; + } + + public: + std::function send_data; + + + enum STPv2_OPCODE + { + NUL = 0x0, + M8 = 0x1, + MERR = 0x2, + C8 = 0x3, + D8 = 0x4, + D16 = 0x5, + D32 = 0x6, + D64 = 0x7, + D8MTS = 0x8, + D16MTS = 0x9, + D32MTS = 0xA, + D64MTS = 0xB, + FLAG_TS = 0xE, + Extension = 0xF, + VERSION = 0xF00, + TRIG = 0xF06, + TRIG_TS = 0xF07, + FREQ = 0xF08, + GERR = 0xF2, + C16 = 0xF3, + D8TS = 0xF4, + D16TS = 0xF5, + D32TS = 0xF6, + D64TS = 0xF7, + D8M = 0xF8, + D16M = 0xF9, + D32M = 0xFA, + D64M = 0xFB, + FLAG = 0xFE, + ASYNC = 0xFFFF, + }; + + + void reset() + { + data_to_send = 0x0; + data_completed = 0x0; + current_master = 0x0; + current_channel = 0x0; + } + + + template + void send_packet(STPv2_OPCODE opcode, T payloads) + { + if (opcode > 0xF) + { + add_data(0xF, 4); + } + add_data((opcode) & 0xF, 4); + + add_data(nibbles_revers(payloads), sizeof(T)*8); + } + + void send_flag_packet(uint8_t master_id, uint16_t channel_id, bool is_trigger, uint64_t time_stamp = 0) + { + if (master_id != current_master) + { + // send master id + current_master = master_id; + current_channel = 0x0; + send_packet(STPv2::STPv2_OPCODE::M8, (uint8_t)current_master); + + } + + if (channel_id != current_channel) + { + // channel id + current_channel = channel_id; + send_packet(STPv2::STPv2_OPCODE::C8, (uint8_t)current_channel); + } + + + if (is_trigger) + { + // Not Supported + } + else + { + if(time_stamp != 0) + { + add_data(FLAG_TS & 0xF, 4); + send_timestamp(16, time_stamp); + } + else + { + add_data(0xF,4); + add_data(0xE,4); + } + } + + } + + template + void send_data_packet(uint8_t master_id, uint16_t channel_id, T data, bool is_mark, uint64_t time_stamp = 0) + { + STPv2_OPCODE opcode[2][2][4] = { { + {D8, D16, D32, D64}, + {D8M, D16M, D32M, D64M} + }, + { + {D8TS, D16TS, D32TS, D64TS}, + {D8MTS, D16MTS, D32MTS, D64MTS} + } + }; + + if (master_id != current_master) + { + // send master id + current_master = master_id; + current_channel = 0x0; + send_packet(STPv2::STPv2_OPCODE::M8, (uint8_t)current_master); + + } + + if (channel_id != current_channel) + { + // channel id + current_channel = channel_id; + send_packet(STPv2::STPv2_OPCODE::C8, (uint8_t)current_channel); + } + int index = sizeof(T) == 1 ? 0 : sizeof(T) == 2 ? 1 : sizeof(T) == 4 ? 2 : 3; + send_packet(opcode[time_stamp != 0][is_mark][index], data); + + + if(time_stamp != 0) + { + send_timestamp(16, time_stamp); + } + } + + template + void send_timestamp(int size, T data) + { + // The STM-500 only generates STPv2NAT timestamps + // TS_PACKET = size ( number of nibbles) , nibbles1, ... + // Max size = 16 + if (size == 16) + { + add_data(0xE, 4); + } + else if (size == 14) + { + add_data(0xD, 4); + } + else + { + add_data(size & 0xF, 4); + } + + if (size != 0) + { + add_data(nibbles_revers(data), sizeof(T)*8); + } + } + }; + } + + + + + + //! AXI + slave port AXI; + //! HWE0 + slave port HWE0; + //! HWE1 + slave port HWE1; + //! HWE2 + slave port HWE2; + //! HWE3 + slave port HWE3; + //! HWE4 + slave port HWE4; + //! HWE5 + slave port HWE5; + //! HWE6 + slave port HWE6; + //! HWE7 + slave port HWE7; + //! HWE8 + slave port HWE8; + //! HWE9 + slave port HWE9; + //! HWE10 + slave port HWE10; + //! HWE11 + slave port HWE11; + //! HWE12 + slave port HWE12; + //! HWE13 + slave port HWE13; + //! HWE14 + slave port HWE14; + //! HWE15 + slave port HWE15; + //! HWE16 + slave port HWE16; + //! HWE17 + slave port HWE17; + //! HWE18 + slave port HWE18; + //! HWE19 + slave port HWE19; + //! HWE20 + slave port HWE20; + //! HWE21 + slave port HWE21; + //! HWE22 + slave port HWE22; + //! HWE23 + slave port HWE23; + //! HWE24 + slave port HWE24; + //! HWE25 + slave port HWE25; + //! HWE26 + slave port HWE26; + //! HWE27 + slave port HWE27; + //! HWE28 + slave port HWE28; + //! HWE29 + slave port HWE29; + //! HWE30 + slave port HWE30; + //! HWE31 + slave port HWE31; + //! HWE32 + slave port HWE32; + //! HWE33 + slave port HWE33; + //! HWE34 + slave port HWE34; + //! HWE35 + slave port HWE35; + //! HWE36 + slave port HWE36; + //! HWE37 + slave port HWE37; + //! HWE38 + slave port HWE38; + //! HWE39 + slave port HWE39; + //! HWE40 + slave port HWE40; + //! HWE41 + slave port HWE41; + //! HWE42 + slave port HWE42; + //! HWE43 + slave port HWE43; + //! HWE44 + slave port HWE44; + //! HWE45 + slave port HWE45; + //! HWE46 + slave port HWE46; + //! HWE47 + slave port HWE47; + //! HWE48 + slave port HWE48; + //! HWE49 + slave port HWE49; + //! HWE50 + slave port HWE50; + //! HWE51 + slave port HWE51; + //! HWE52 + slave port HWE52; + //! HWE53 + slave port HWE53; + //! HWE54 + slave port HWE54; + //! HWE55 + slave port HWE55; + //! HWE56 + slave port HWE56; + //! HWE57 + slave port HWE57; + //! HWE58 + slave port HWE58; + //! HWE59 + slave port HWE59; + //! HWE60 + slave port HWE60; + //! HWE61 + slave port HWE61; + //! HWE62 + slave port HWE62; + //! HWE63 + slave port HWE63; + //! DebugAPB + slave port DebugAPB; + //! TRIGOUTSPTE + master port TRIGOUTSPTE; + //! TRIGOUTSW + master port TRIGOUTSW; + //! TRIGOUTHETE + master port TRIGOUTHETE; + //! ASYNCOUT + master port ASYNCOUT; + + // 64bit ATB Packet + master port ATB; + + + composition + { + // TODO + // There are 65,536 channels implemented as a stimulus port per channel + // 16MB in the AXI memory space + axi_busslave : PVBusSlave(size = 0x100000000); // Max 32 bit address space + + debug_apb_busslave : PVBusSlave(size = 0x1000); + } + + resources + { + sg::EventSource* trace; + sg::EventSource* trace_stm; + STPv2 stp; + stmAPB stm_reg; + sg::SchedulerInterfaceForComponents* sci; + uint64_t stm_local_time; + } + + behavior reset(int level) + { + composition.reset(level); + stp.reset(); + stm_local_time = 0x0; + + } + behavior init() + { + composition.init(); + + // create EventSource object + trace = new sg::EventSource(); + + // provide trace name and description + trace->setName( "STM_ATB_VALUE" ); + trace->setDescription( "ATB 64 bit value from STM" ); + + trace->AddField("ATB", + "Value of ATB 64 bit data from STM", + MTI::EventFieldType::MTI_UNSIGNED_INT, + sizeof(uint64_t) ); + + + // create EventSource object + trace_stm = new sg::EventSource(); + + // provide trace name and description + trace_stm->setName( "STM_PORT" ); + trace_stm->setDescription( "STM stimulus Port" ); + + trace_stm->AddField("MasterID", + "Master ID", + MTI::EventFieldType::MTI_UNSIGNED_INT, + sizeof(uint8_t)); + trace_stm->AddField("channelID", + "channel ID", + MTI::EventFieldType::MTI_UNSIGNED_INT, + sizeof(uint8_t)); + trace_stm->AddField("DATA", + "Data Written to stimulus port", + MTI::EventFieldType::MTI_UNSIGNED_INT, + sizeof(uint64_t)); + trace_stm->AddField("MARK", + "Is Mark Data", + MTI::EventFieldType::MTI_BOOL, + sizeof(bool)); + trace_stm->AddField("Timestamp", + "Timestamp of STM packet, zero mean no Timestamp packet", + MTI::EventFieldType::MTI_UNSIGNED_INT, + sizeof(uint64_t)); + + + + addTraceSource( trace ); + + addTraceSource( trace_stm ); + + sci = getSchedulerInterfaceForComponents( + getSimulationContext(), getHierarchicalName().c_str(), getInstancePath()); + + stp.send_data = std::bind(&COMPONENT_CLASS_NAME(STM500)::send_data, this, std::placeholders::_1); + } + + behavior is_ATB_active() : bool + { + return trace->isActive() || ATB.setValue.implemented(); + } + + behavior send_data(uint64_t data):void + { + // printf("Sending ATB = %lx", data); + + if (trace->isActive()) + { + trace->fire(data); + } + + if (ATB.setValue.implemented()) + { + ATB.setValue(data); + } + } + + + + connection + { + self.AXI => axi_busslave.pvbus_s; + axi_busslave.device => self.AXIdevice; + + self.DebugAPB => debug_apb_busslave.pvbus_s; + debug_apb_busslave.device => self.DebugAPBdevice; + } + behavior AXIRead(pv::bus_addr_t addr) : uint32_t + { + uint32_t data = 0; // All locations are write-only. Read accesses return zero + + // printf(" [%s] Called addr = %lx data = %x \n", __FUNCTION__, addr, data); + return data; + } + + behavior AXIWrite(pv::bus_addr_t addr, uint32_t data) + { + // printf(" [%s] Called addr = %lx data = %c \n", __FUNCTION__, addr, (uint8_t)data); + } + + behavior DebugAPBRead(pv::bus_addr_t addr) : uint32_t + { + uint32_t data = 0; + if ( (addr + 4) <= sizeof(stm_reg)) + { + memcpy(&data, (uint8_t *)&stm_reg + addr, 4); + } + // printf(" [%s] Called addr = %lx data = %x\n", __FUNCTION__, addr, data); + + return data; + } + + behavior DebugAPBWrite(pv::bus_addr_t addr, uint32_t data) + { + if ( (addr + 4) <= sizeof(stm_reg)) + { + memcpy((uint8_t *)&stm_reg + addr, &data, 4); + } + // printf(" [%s] Called addr = %lx data = %x\n", __FUNCTION__, addr, data); + + } + + internal slave port AXIdevice + { + // Pass on read/write requests to registerRead()/registerWrite(). + behavior read(pv::ReadTransaction tx) + : pv::Tx_Result + { + // Unaligned accesses are not supported. All accesses must be aligned to the access size. + if (tx.getAccessWidth() > pv::ACCESS_32_BITS || !tx.isAligned()) return tx.generateAbort(); + // Always do an aligned 32-bit read and let the bus extract the appropriate data + return tx.setReturnData32((uint32_t)AXIRead(tx.getAddress() & ~3)); + } + + behavior write(pv::WriteTransaction tx) + : pv::Tx_Result + { + + if (!is_ATB_active() || ( (stm_reg.STMTCSR & STMTCSR_EN) == 0x0)) + { + return tx.writeComplete(); + } + + // Data accesses must be aligned to the bottom of the 8-byte + // every data packet access must have address bits[2:0] == 0b000 + // bool access_aligned = ((tx.getAddress() & 0x7) != 0); + + + + // Non-data accesses must be written as zero and the implementation must ignore the data value. + // bool data_written_is_zero = (tx.getData32() == 0x0); + + // pv::AccessWidth = tx.getAccessWidth(); + + // uint32_t size = tx.getTransactionByteSize(); + + // Unaligned accesses are not supported. All accesses must be aligned to the access size. + + + /* The master identification is based on all of the following: + * 1. Whether the access is Secure or Non-secure. + * 2. The upper bits of the AXI address. + * + * MasterID + * Bit[7] : 0 + * Bit[6] : AWPROTS[1] + * Bits[5:0] : AWADDRS[29:24] + */ + uint8_t masterID = ((tx.getAddress() & (0x3F<<24)) >> 24) | ((tx.isNonSecure() ? 0x1 : 0x0)<<6); + + + + // Each extended stimulus port occupies 256 consecutive bytes in the memory map. + // 1 stimulus port = 0x00 - 0xFF + // 16 * 256 = 4KB + // 16 stimulus ports occupy a 4KB + + // + + // 16MB of address space + // + + uint8_t stimulus_port_reg = tx.getAddress() & 0xFF; + + uint16_t port_num = (tx.getAddress() >> 8) & 0xF; + + + // Bit 7 : 1: Invariant Timing data accesses, 0: Guaranteed + // Bit 5 : 1: No Data (Flag, Triger) , 0 : Data + // Bit 4 : 1: Not Marked , 0: Marked + // Bit 3 : 1: No Timestamp, 0: Timestamped + + bool is_no_data = (stimulus_port_reg & 0x1<<5) ? true : false; + bool is_mark = (stimulus_port_reg & 0x1<<4) ? false : true; + bool enableTimestamp = (stimulus_port_reg & 0x1<<3) ? false : true; + + + uint64_t time_stamp = 0x0; + if (enableTimestamp) + { + + uint64_t global_time = sci->getCurrentSimulatedTime(nullptr); + uint64_t local_time = 0; + + sg::SchedulerThread * current_thread = sci->currentThread(); + if(current_thread) + { + sg::SchedulerRunnable * runnable = current_thread->getRunnable(); + runnable->getThreadProperty(sg::SchedulerRunnable::TP_LOCAL_TIME, local_time); + runnable->setThreadProperty(sg::SchedulerRunnable::TP_LOCAL_TIME, local_time+1); + runnable->getThreadProperty(sg::SchedulerRunnable::TP_LOCAL_TIME, local_time); + } + + // printf(" global_time = %lx, local_time = %lx \n", global_time, local_time); + time_stamp = global_time + local_time + stm_local_time; + stm_local_time++; + } + // printf("Time : %lx \n", time_stamp); + + if (!is_no_data) + { + switch(tx.getAccessWidth()) + { + case pv::ACCESS_8_BITS: + { + stp.send_data_packet(masterID, port_num, (uint8_t)tx.getData8(), is_mark, time_stamp ); + break; + } + case pv::ACCESS_16_BITS: + { + stp.send_data_packet(masterID, port_num, (uint16_t)tx.getData16(), is_mark, time_stamp ); + break; + } + case pv::ACCESS_32_BITS: + { + stp.send_data_packet(masterID, port_num, (uint32_t)tx.getData32(), is_mark, time_stamp ); + break; + } + case pv::ACCESS_64_BITS: + { + stp.send_data_packet(masterID, port_num, (uint64_t)tx.getData64(), is_mark, time_stamp ); + break; + } + default: + stp.send_data_packet(masterID, port_num, (uint8_t)tx.getData32(), is_mark, time_stamp ); + + } + stp.send_data_packet(masterID, port_num, (uint8_t)tx.getData32(), is_mark, time_stamp ); + } + else + { + stp.send_flag_packet(masterID, port_num, is_mark, time_stamp); + } + + if(trace_stm->isActive()) + { + if (!is_no_data) + { + trace_stm->fire(masterID, port_num, (uint64_t)tx.getData32(), is_mark, time_stamp ); + } + else + { + trace_stm->fire(masterID, port_num, 0x0, is_mark, time_stamp); + } + } + + + AXIWrite(tx.getAddress(), + tx.getData32()); + return tx.writeComplete(); + } + + behavior debugRead(pv::ReadTransaction tx) : pv::Tx_Result + { + return AXIdevice.read(tx); + } + + behavior debugWrite(pv::WriteTransaction tx) : pv::Tx_Result + { + return AXIdevice.write(tx); + } + } + + + internal slave port DebugAPBdevice + { + // Pass on read/write requests to registerRead()/registerWrite(). + behavior read(pv::ReadTransaction tx) + : pv::Tx_Result + { + if (tx.getAccessWidth() > pv::ACCESS_32_BITS || !tx.isAligned()) return tx.generateAbort(); + // Always do an aligned 32-bit read and let the bus extract the appropriate data + return tx.setReturnData32((uint32_t)DebugAPBRead(tx.getAddress() & ~3)); + } + + behavior write(pv::WriteTransaction tx) + : pv::Tx_Result + { + DebugAPBWrite(tx.getAddress(), + tx.getData32()); + return tx.writeComplete(); + } + + behavior debugRead(pv::ReadTransaction tx) : pv::Tx_Result + { + return DebugAPBdevice.read(tx); + } + + behavior debugWrite(pv::WriteTransaction tx) : pv::Tx_Result + { + return DebugAPBdevice.write(tx); + } + } + +} diff --git a/fast-models-examples/STM_Demo/README.txt b/fast-models-examples/STM_Demo/README.txt new file mode 100644 index 00000000..7b75eaa4 --- /dev/null +++ b/fast-models-examples/STM_Demo/README.txt @@ -0,0 +1,48 @@ +This Package contain Demo on how to model STM and use test software to use this demo model. This model is not complete and for demo purpose only. + +STM500 model is implemented in Model/FVP_STM/LISA/STM500.lisa + +It supports two different trace sources to populate STM ATB data. +STM_PORT: Human readable syntax for data trace +STM_ATB_VALUE : Match ATB data from STM500 to match hardware packet + +Model also supports port "master port ATB;", Any device can connect to the ATB port of STM500 model to get Packet. + + +Build Model +============ +setenv PVLIB_HOME +setenv SYSTEMC_HOME + + +cd Model/FVP_STM/Build_Cortex-A57 +sh build.sh + + +Build Software +================ + +Configure your Arm DS environment to run Arm Compiler 6 from the command-line: +https://developer.arm.com/docs/101470/1900/configure-arm-development-studio/register-a-compiler-toolchain/configure-a-compiler-toolchain-for-the-arm-ds-command-prompt + + +cd SW_Test +sh build.sh + + +Run Model with Software Test +============================== +Option 1: +Without Trace plugin +Model/FVP_STM/Build_Cortex-A57/Linux64-Release-GCC-4.9/isim_system -a SW_Test/image.axf + +Option 2: +With Trace PLugin GenericTrace.so to get STM_PORT trace + +Model/FVP_STM/Build_Cortex-A57/Linux64-Release-GCC-4.9/isim_system -a SW_Test/image.axf --plugin $PVLIB_HOME/plugins/Linux64_GCC-4.9/GenericTrace.so -C TRACE.GenericTrace.trace-sources=STM_PORT + +Option 3: +With Trace PLugin GenericTrace.so to get STM_ATB_VALUE trace + + +Model/FVP_STM/Build_Cortex-A57/Linux64-Release-GCC-4.9/isim_system -a SW_Test/image.axf --plugin $PVLIB_HOME/plugins/Linux64_GCC-4.9/GenericTrace.so -C TRACE.GenericTrace.trace-sources=STM_ATB_VALUE diff --git a/fast-models-examples/STM_Demo/SW_Test/build.sh b/fast-models-examples/STM_Demo/SW_Test/build.sh new file mode 100644 index 00000000..ac9a932b --- /dev/null +++ b/fast-models-examples/STM_Demo/SW_Test/build.sh @@ -0,0 +1,15 @@ + +# Requires a recent armclang on the PATH, e.g.: +# eval `setup_wh_comp 'ARMCC:TestableTools:0.0::trunk:regime=rel|checking=none'` + +# Configure your Arm DS environment to run Arm Compiler 6 from the command-line: + +#https://developer.arm.com/docs/101470/1900/configure-arm-development-studio/register-a-compiler-toolchain/configure-a-compiler-toolchain-for-the-arm-ds-command-prompt + + +armclang -c -g --target=aarch64-arm-none-eabi $CFLAGS hello_world.c +armclang -c -g --target=aarch64-arm-none-eabi $CFLAGS startup.s +armclang -c -g --target=aarch64-arm-none-eabi $CFLAGS pl011_uart.c +armclang -c -g --target=aarch64-arm-none-eabi $CFLAGS stm.c +armlink --scatter=scatter.txt --entry=start64 $CFLAGS hello_world.o startup.o pl011_uart.o stm.o -o image.axf +fromelf --text -c image.axf --output=disasm.txt diff --git a/fast-models-examples/STM_Demo/SW_Test/hello_world.c b/fast-models-examples/STM_Demo/SW_Test/hello_world.c new file mode 100644 index 00000000..45c7726e --- /dev/null +++ b/fast-models-examples/STM_Demo/SW_Test/hello_world.c @@ -0,0 +1,42 @@ +#include +#include "pl011_uart.h" +#include "stm.h" + +#define USE_STM + + +#ifdef USE_STM +struct STM *gSTM; +# define PLATFORM_STM_AXI_ADDRESS 0x28000000ULL +# define PLATFORM_STM_APB_ADDRESS 0x20100000ULL +#else +# define PLATFORM_UART_ADDRESS 0x40004000 +#endif + +int fputc(int c, FILE *f) { + #ifdef USE_STM + return stm_fputc(gSTM, c, f); + #else + return uart_fputc(c,f); + #endif +} + +int main (void) { + #ifdef USE_STM + /* Initialize the STM */ + struct STM stm = { 0 }; + gSTM = (struct STM *) &stm; + + stmInit( + gSTM, + (struct stmAPB *) PLATFORM_STM_APB_ADDRESS, + (struct stmAXI *) PLATFORM_STM_AXI_ADDRESS + ); + stmSendString(gSTM, 0, "Test STM String\n"); + // stmSendString(gSTM, 1, "Test STM String\n"); + #else + uartInit((void*)(PLATFORM_UART_ADDRESS)); + #endif + printf("hello world\n"); + return 0; +} diff --git a/fast-models-examples/STM_Demo/SW_Test/pl011_uart.c b/fast-models-examples/STM_Demo/SW_Test/pl011_uart.c new file mode 100644 index 00000000..4ffd0bdd --- /dev/null +++ b/fast-models-examples/STM_Demo/SW_Test/pl011_uart.c @@ -0,0 +1,110 @@ +//================================================================== +// Copyright ARM Ltd 2005-2011. All rights reserved. +// +// Code for PL011 UART - retargets fputc() +//================================================================== + +#include +#include "pl011_uart.h" + +struct __FILE { + int handle; +}; + +/* FILE is typedef’d in stdio.h. */ + +FILE __stdout; + +// Useful defines for control/status registes +#define PL011_LCR_WORD_LENGTH_8 (0x60) +#define PL011_LCR_WORD_LENGTH_7 (0x40) +#define PL011_LCR_WORD_LENGTH_6 (0x20) +#define PL011_LCR_WORD_LENGTH_5 (0x00) + +#define PL011_LCR_FIFO_ENABLE (0x10) +#define PL011_LCR_FIFO_DISABLE (0x00) + +#define PL011_LCR_TWO_STOP_BITS (0x08) +#define PL011_LCR_ONE_STOP_BIT (0x00) + +#define PL011_LCR_PARITY_ENABLE (0x02) +#define PL011_LCR_PARITY_DISABLE (0x00) + +#define PL011_LCR_BREAK_ENABLE (0x01) +#define PL011_LCR_BREAK_DISABLE (0x00) + +#define PL011_IBRD_DIV_38400 (0x27) +#define PL011_FBRD_DIV_38400 (0x09) + +#define PL011_ICR_CLR_ALL_IRQS (0x07FF) + +#define PL011_FR_TXFF_FLAG (0x20) +#define PL011_FR_RXFF_FLAG (0x40) + +#define PL011_CR_UART_ENABLE (0x01) +#define PL011_CR_TX_ENABLE (0x0100) +#define PL011_CR_RX_ENABLE (0x0200) + + +struct pl011_uart { + volatile unsigned int UARTDR; // +0x00 + volatile unsigned int UARTECR; // +0x04 + const volatile unsigned int unused0[4]; // +0x08 to +0x14 reserved + const volatile unsigned int UARTFR; // +0x18 - RO + const volatile unsigned int unused1; // +0x1C reserved + volatile unsigned int UARTILPR; // +0x20 + volatile unsigned int UARTIBRD; // +0x24 + volatile unsigned int UARTFBRD; // +0x28 + volatile unsigned int UARTLCR_H; // +0x2C + volatile unsigned int UARTCR; // +0x30 + volatile unsigned int UARTIFLS; // +0x34 + volatile unsigned int UARTIMSC; // +0x38 + const volatile unsigned int UARTRIS; // +0x3C - RO + const volatile unsigned int UARTMIS; // +0x40 - RO + volatile unsigned int UARTICR; // +0x44 - WO + volatile unsigned int UARTDMACR; // +0x48 +}; + +// Instance of the dual timer +struct pl011_uart* uart; + + +// ------------------------------------------------------------ + +void uartInit(void* addr) { + uart = (struct pl011_uart*) addr; + + // Ensure UART is disabled + uart->UARTCR = 0x0; + + // Set UART 0 Registers + uart->UARTECR = 0x0; // Clear the recieve status (i.e. error) register + uart->UARTLCR_H = 0x0 | PL011_LCR_WORD_LENGTH_8 | PL011_LCR_FIFO_DISABLE | PL011_LCR_ONE_STOP_BIT | PL011_LCR_PARITY_DISABLE | PL011_LCR_BREAK_DISABLE; + + uart->UARTIBRD = PL011_IBRD_DIV_38400; + uart->UARTFBRD = PL011_FBRD_DIV_38400; + + uart->UARTIMSC = 0x0; // Mask out all UART interrupts + uart->UARTICR = PL011_ICR_CLR_ALL_IRQS; // Clear interrupts + + uart->UARTCR = 0x0 | PL011_CR_UART_ENABLE | PL011_CR_TX_ENABLE | PL011_CR_RX_ENABLE; + + return; +} + +// ------------------------------------------------------------ + +int uart_fputc(int c, FILE *f) { + // Wait until FIFO or TX register has space + while ((uart->UARTFR & PL011_FR_TXFF_FLAG) != 0x0) {} + + // Write packet into FIFO/tx register + uart->UARTDR = c; + + // Model requires us to manually send a carriage return + if ((char)c == '\n') { + while ((uart->UARTFR & PL011_FR_TXFF_FLAG) != 0x0) {} + uart->UARTDR = '\r'; + } + return 0; +} diff --git a/fast-models-examples/STM_Demo/SW_Test/pl011_uart.h b/fast-models-examples/STM_Demo/SW_Test/pl011_uart.h new file mode 100644 index 00000000..5e7f387e --- /dev/null +++ b/fast-models-examples/STM_Demo/SW_Test/pl011_uart.h @@ -0,0 +1,18 @@ +// ---------------------------------------------------------- +// Copyright ARM Ltd 2005-2011. All rights reserved. +// +// Code for PL011 UART - retargets fputc() +// ---------------------------------------------------------- + +#ifndef __uart_h +#define __uart_h + +void uartInit(void* addr); // Must be called before printf() or uartSendString() is called! +void uartSendString(const char*); +int uart_fputc(int c, FILE *f); + +#endif + +// ---------------------------------------------------------- +// End of pl011_uart.h +// ---------------------------------------------------------- diff --git a/fast-models-examples/STM_Demo/SW_Test/scatter.txt b/fast-models-examples/STM_Demo/SW_Test/scatter.txt new file mode 100644 index 00000000..ff3564d1 --- /dev/null +++ b/fast-models-examples/STM_Demo/SW_Test/scatter.txt @@ -0,0 +1,16 @@ +ROM_LOAD 0x00000000 0x00010000 +{ + ROM_EXEC +0x0 + { + startup.o(BOOT, +FIRST) + * (+RO) + } + + RAM_EXEC 0x04000000 0x10000 + { + * (+RW, +ZI) + } + + ARM_LIB_STACKHEAP 0x04010000 ALIGN 64 EMPTY 0x10000 + {} +} \ No newline at end of file diff --git a/fast-models-examples/STM_Demo/SW_Test/startup.s b/fast-models-examples/STM_Demo/SW_Test/startup.s new file mode 100644 index 00000000..a4bdb1c6 --- /dev/null +++ b/fast-models-examples/STM_Demo/SW_Test/startup.s @@ -0,0 +1,38 @@ +// ------------------------------------------------------------ +// ARMv8-A AArch64 Startup Example +// +// Copyright Arm Ltd 2017. All rights reserved. +// ------------------------------------------------------------ + + .section BOOT,"ax" // Define an executable ELF section, BOOT + .align 3 // Align to 2^3 byte boundary + + .global start64 + .type start64, "function" +start64: + + + // Which core am I + // ---------------- + MRS x0, MPIDR_EL1 + AND x0, x0, #0xFFFF // Mask off to leave Aff0 and Aff1 + CBZ x0, boot // If not *.*.0.0, then go to sleep +sleep: + WFI + B sleep +boot: + + + // Disable trapping of CPTR_EL3 accesses or use of Adv.SIMD/FPU + // ------------------------------------------------------------- + MSR CPTR_EL3, xzr // Clear all trap bits + + // Branch to scatter loading and C library init code + .global __main + B __main + + +// ------------------------------------------------------------ +// End of file +// ------------------------------------------------------------ + diff --git a/fast-models-examples/STM_Demo/SW_Test/stm.c b/fast-models-examples/STM_Demo/SW_Test/stm.c new file mode 100644 index 00000000..615a43d9 --- /dev/null +++ b/fast-models-examples/STM_Demo/SW_Test/stm.c @@ -0,0 +1,736 @@ +/* + * STM Example + * + * Copyright (c) 2015-2016 ARM, Inc. All rights reserved. + * + */ + +#include +#include "stm.h" + +/* + * Coresight Lock Access + */ +void stmUnlock(struct STM *stm) +{ + /* + * Only unlock if locks are required. + * + * Technically this would be true of any + * APB transaction that didn't come through + * the CoreSight DAP.. + */ + if (stm->APB->STMLSR & STMLSR_SLI) + { + stm->APB->STMLAR = STMLAR_UNLOCK; + while ((stm->APB->STMLSR & STMLSR_SLK) == STMLSR_SLK); + // wait for unlock to be reflected + } +} + +void stmLock(struct STM *stm) +{ + /* + * Only lock if locks are required. + */ + if (stm->APB->STMLSR & STMLSR_SLI) + { + /* and not already locked.. */ + if (!(stm->APB->STMLSR & STMLSR_SLK)) + { + stm->APB->STMLAR = STMLAR_LOCK; + while ((stm->APB->STMLSR & STMLSR_SLK) == 0x0); + // wait for lock to be reflected + } + } +} + +static void stmTCSRSet(struct STM *stm, unsigned int flags) +{ + stm->APB->STMTCSR = (stm->APB->STMTCSR | flags); +} + +static void stmTCSRClr(struct STM *stm, unsigned int flags) +{ + stm->APB->STMTCSR = (stm->APB->STMTCSR & (~flags)); +} + + +/* + * Enable STM tracing + */ + +void stmEnable(struct STM *stm) +{ + stmTCSRSet(stm, STMTCSR_EN); +} + +void stmDisable(struct STM *stm) +{ + /* + * STM Architecture Spec v1.1 (IHI00054B) 2.3.10: + * ~~ + * To ensure that all writes to the STM stimulus ports are traced + * before disabling the STM, ARM recommends that software writes + * to the stimulus port then reads from any stimulus port before + * clearing STMTCSR.EN. This is only required if the same piece of + * software is writing to the stimulus ports and disabling the STM. + * ~~ + * + * Technically.. we might want a DSB barrier here too.. + */ + volatile unsigned int dummy = STM32(stm->AXI, 0, G_FLAG); + + stmTCSRClr(stm, STMTCSR_EN); +} + +/* + * Configuration helpers + */ + +void stmWaitForIdle(struct STM *stm) +{ + while (stm->APB->STMTCSR & STMTCSR_BUSY); +} + +unsigned int stmSynchronization(struct STM *stm, unsigned int en) +{ + switch (stm->FEAT1R & STMFEAT1_SYNCEN) { + case STMFEAT1_SYNCEN_OK: + if (en) { + stmTCSRSet(stm, STMTCSR_SYNCEN); + } else { + stmTCSRClr(stm, STMTCSR_SYNCEN); + } + return en; + + /* + * Periodic sync might be always enabled, or not + * available, in which case we just return the + * current state + */ + case STMFEAT1_SYNCEN_ALWAYS: + return 1; + + case STMFEAT1_SYNCEN_NOIMPL: + default: + return 0; + } +} + +unsigned int stmCompression(struct STM *stm, unsigned int en) +{ + unsigned int spcomp = stm->FEAT2R & STMFEAT2_SPCOMP; + + switch (spcomp) { + case STMFEAT2_SPCOMP_OK: + if (en) { + stmTCSRSet(stm, STMTCSR_COMPEN); + } else { + stmTCSRClr(stm, STMTCSR_COMPEN); + } + return en; + + /* + * Compression might be always enabled, or not + * available, in which case we just return the + * current state + */ + case STMFEAT2_SPCOMP_ALWAYS: + return 1; + + case STMFEAT2_SPCOMP_NOIMPL: + default: + return 0; + } +} + +unsigned int stmTimestamping(struct STM *stm, unsigned int en) +{ + /* + * Timestamping not supported -- don't do anything + */ + if ((stm->FEAT1R & STMFEAT1_TS) == STMFEAT1_TS_NOIMPL) + return 0; + + /* + * Timestamping is supported but we don't care if they're + * differential or absolute.. just enable it per request + */ + if (en) { + stmTCSRSet(stm, STMTCSR_TSEN); + } else { + stmTCSRClr(stm, STMTCSR_TSEN); + } + + return en; +} + +/* + * stmTRACEID(stm, traceid) + * + * Set STM's TRACEID (which goes out over ATB bus ATBID) + * + * Note it is illegal per CoreSight to set the trace ID + * to 0x00 or one of the reserved values (0x70 onwards) + * (see IHI0029D D4.2.4 Special trace source IDs). + * + * This function doesn't do anything if you pass one of + * those values, and will return 0 for an invalid value.. + */ +unsigned int stmTRACEID(struct STM *stm, unsigned int traceid) +{ + unsigned int tcsr; + unsigned int current_traceid; + + tcsr = stm->APB->STMTCSR; + current_traceid = ((tcsr >> TRACEID_SHIFT) & TRACEID_MASK); + + if ((traceid > 0x00) && (traceid < 0x70)) { + /* + * We try not to corrupt the Trace ID if it's already + * valid -- it implies someone already set it up, either + * an external debugger or previous software. + * + * So, if we got a Trace ID that's in the valid range, + * and the Trace ID is currently invalid, set it, + * otherwise try not to do anything. + */ + if (!current_traceid) { + traceid = traceid & TRACEID_MASK; + tcsr = (stm->APB->STMTCSR & ~(TRACEID_MASK << TRACEID_SHIFT)); + stm->APB->STMTCSR = (tcsr | (traceid << TRACEID_SHIFT)); + + return traceid; + } + } + + return current_traceid; +} + +/* + * stmHEDisableAll(stm) + * + * Disables HW Event tracing -- note that there is also a + * STMTCSR.HWTEN bit which would globally disable this, but on + * ARM's STM when synthesized for HW Event Trace, it's not + * implemented. + * + * For now we're assuming that there are only 32 events (we + * ignore the value of STMHEFEAT1R.NUMHE) and just check to + * see if the STMHEERR and STMHETER registers exist so we + * can disable the events. + */ +void stmHEDisableEventsAll(struct STM *stm) +{ + if ((stm->FEAT1R & STMFEAT1_HWTEN) == STMFEAT1_HWTEN_NOIMPL) { + if (stm->HE) { + stm->HE->STMHEBSR = 0x00000000; + + if (stm->HEFEAT1R & STMHEFEAT1_HEERR) + stm->HE->STMHEERR = 0x00000000; + + if (stm->HEFEAT1R & STMHEFEAT1_HETER) + stm->HE->STMHETER = 0x00000000; + } + } else { + if ((stm->FEAT1R & STMFEAT1_HWTEN) == STMFEAT1_HWTEN_OK) { + stmTCSRClr(stm, STMTCSR_HWTEN); + } + } +} + + +void stmHEEnable(struct STM *stm) +{ + if (stm->HE) + stm->HE->STMHEMCR = (stm->HE->STMHEMCR | 0x1); +} + +void stmHEDisable(struct STM *stm) +{ + if (stm->HE) + stm->HE->STMHEMCR = (stm->HE->STMHEMCR & ~(0x1)); +} + +unsigned int stmNumStimulusPorts(struct STM *stm) +{ + return (stm->DEVID & 0x1ffff); +} + +unsigned int stmEnablePortsAll(struct STM *stm) +{ + if (1) { + /* + * Set STMPSCR.PORTCTL to 0x0 to ensure port selection is not + * used. STMPSCR.PORTSEL is ignored and STMSPER and STMSPTER + * bits apply equally to all groups of ports. + * + * Whether the STM has 32 or 65536 ports, they'll all be + * enabled. + */ + stm->APB->STMSPSCR = 0x00000000; + } else { + /* Alternatively: + * + * Set STMPSCR.PORTCTL to 0x3 to ensure the port selection + * applies to both STMSPER and STMSPTER. + * + * Set STMPSCR.PORTSEL to 0x800 which selects all stimulus + * port groups in the same way that STMPSCR.PORTCTL = 0x0 + * would effect. + */ + stm->APB->STMSPSCR = 0x80000003; + } + + if ((stm->FEAT2R & STMFEAT2_SPER) == STMFEAT2_SPER_OK) + stm->APB->STMSPER = 0xffffffff; + + if ((stm->FEAT2R & STMFEAT2_SPTER) == STMFEAT2_SPTER_OK) + stm->APB->STMSPTER = 0xffffffff; + + return stmNumStimulusPorts(stm); +} + +unsigned int stmDisablePortsAll(struct STM *stm) +{ + stm->APB->STMSPSCR = 0x00000000; + + if ((stm->FEAT2R & STMFEAT2_SPER) == STMFEAT2_SPER_OK) + stm->APB->STMSPER = 0x00000000; + + if ((stm->FEAT2R & STMFEAT2_SPTER) == STMFEAT2_SPTER_OK) + stm->APB->STMSPTER = 0x00000000; + + return stmNumStimulusPorts(stm); +} + + +/* + * stmSetTimestampFrequency(stm, freq) + * + * Inform trace decoders of the timestamp counter frequency, by + * way of correctly generating FREQ and FREQ_TS packets. Configuring + * this register is not optional if it is writable! + */ + +void stmSetTimestampFrequency(struct STM *stm, unsigned int freq) +{ + if (stm->FEAT1R & STMFEAT1_TSFREQ) { + stm->APB->STMTSFREQR = freq; + } +} + +/* + * stmForceTimestamp(stm) + * + * If possible, use the STMTSSTIMR register to force output of a + * Timestamp packet, usually by upgrading an existing data packet, + * for instance D32M -> D32MTS. + * + * If STMTCSR.TSEN is 0 then nothing will happen. + */ + +void stmForceTimestamp(struct STM *stm) +{ + if (stm->FEAT1R & STMFEAT1_FORCETS) + stm->APB->STMTSSTIMR = 1; +} + +/* + * stmSetSyncFrequency(stm, bytes) + * + * Request the STM periodically output an ASYNC packet every "bytes" + * of trace output. This will only have an effect if STMTCSR.SYNCEN + * is enabled, if implemented. + */ + +void stmSetSyncFrequency(struct STM *stm, unsigned int bytes) +{ + /* We only support setting it in bytes.. */ + if ((stm->FEAT1R & STMFEAT1_SYNCR) > STMFEAT1_SYNCR_NOMODE) { + stm->APB->STMSYNCR = (bytes & 0xfff); + } +} + +/* + * stmInitFeatures(stm) + * + * Keep caches of the feature registers in the STM structure so that + * when we read them we're just doing Normal memory accesses and not + * going out to the APB control interface. These registers never + * change, so a Device memory access to them is slow and unecessary. + * + * Perform a run through on all the feature registers we can get a + * hold on, and fix them up so they have "reasonable" values, that + * way we can check for features without being too complicated + * later. + * + * + * Some of the feature checks require STMTCSR.EN to be disabled, so + * this has to be called really very early.. + */ + +void stmInitFeatures(struct STM *stm) +{ + unsigned int i; + + stm->FEAT1R = stm->APB->STMFEAT1R; + stm->FEAT2R = stm->APB->STMFEAT2R; + stm->FEAT3R = stm->APB->STMFEAT3R; + stm->DEVARCH = stm->APB->STMDEVARCH; + stm->DEVID = stm->APB->STMDEVID; + stm->HE = (void *) 0L; + stm->HEFEAT1R = 0; + stm->DMA = (void *) 0L; + + stm->NumPorts = 65536; + stm->DSize = ((stm->FEAT2R & 0xF000) >> 12) ? 64 : 32; + + for (i = 0; i <= 3; i++) { + /* Go over all the STM IMPDEF blocks, save the IDR and find HE and DMA control */ + unsigned int class; + + stm->IMPDEFIDR[i] = stm->APB->IMPDEF[3-i][63]; + class = stm->IMPDEFIDR[i] & 0xF; + + switch (class) { + case 0x1: + stm->HE = (struct stmHE *) ((&stm->APB->IMPDEF[3-i][0])); + stm->HEFEAT1R = stm->HE->STMHEFEAT1R; + break; + case 0x2: + stm->DMA = (struct stmDMA *) ((&stm->APB->IMPDEF[3-i][0])); + break; + } + } + + /* Fix up timestamping */ + if ((stm->FEAT1R & STMFEAT1_TS) == STMFEAT1_TS_RSVD) { + /* Fix up an undefined value as "not implemented" */ + stm->FEAT1R = ( (stm->FEAT1R & (~STMFEAT1_TS)) | STMFEAT1_TS_NOIMPL ); + } + + /* Fix up Synchronization support */ + if ((stm->FEAT1R & STMFEAT1_SYNCR) == STMFEAT1_SYNCR_UNDEF) + { + /* + * STMSYNCR support is defined by the SYNCR reacting to a write. + */ + unsigned int syncf = (stm->FEAT1R & (~STMFEAT1_SYNCR)); + unsigned int syncr; + + stm->APB->STMSYNCR = 0x00001fff; + syncr = stm->APB->STMSYNCR; + + if (syncr == 0x00001fff) { + stm->FEAT1R = syncf | STMFEAT1_SYNCR_OKMODE; + } else if (syncr == 0x00000fff) { + stm->FEAT1R = syncf | STMFEAT1_SYNCR_NOMODE; + } else { + stm->FEAT1R = syncf | STMFEAT1_SYNCR_NOIMPL; + } + } + + if ((stm->FEAT1R & STMFEAT1_SYNCR) > STMFEAT1_SYNCR_NOMODE) + { + /* + * if STMSYNCR exists then STMTCSR.SYNCEN is always 1 + * (STMTCSR note c) + */ + stm->FEAT1R = (stm->FEAT1R & (~STMFEAT1_SYNCEN)) | STMFEAT1_SYNCEN_ALWAYS; + } + else if ((stm->FEAT1R & STMFEAT1_SYNCEN) == STMFEAT1_SYNCEN_UNDEF) + { + /* + * SYNCEN support is defined by the TCSR reacting to a write, + * so perform that test write and fix up stm->FEAT1R to reflect + * whether it's programmable or not.. + */ + stm->APB->STMTCSR = stm->APB->STMTCSR | STMTCSR_SYNCEN; + if (stm->APB->STMTCSR & STMTCSR_SYNCEN) { + stm->FEAT1R = (stm->FEAT1R & (~STMFEAT1_SYNCEN)) | STMFEAT1_SYNCEN_OK; + } + } + + /* Fix up Hardware Trace Enable support */ + if ((stm->FEAT1R & STMFEAT1_HWTEN) == STMFEAT1_HWTEN_UNDEF) + { + /* + * HWTEN support is defined by the TCSR reacting to a write. + */ + stm->APB->STMTCSR = stm->APB->STMTCSR | STMTCSR_HWTEN; + if ((stm->APB->STMTCSR & STMTCSR_HWTEN)) + stm->FEAT1R = (stm->FEAT1R & (~STMFEAT1_HWTEN)) | STMFEAT1_HWTEN_OK; + } + else if ((stm->FEAT1R & STMFEAT1_HWTEN) == STMFEAT1_HWTEN_RSVD) + { + /* + * Fix up an undefined value as "not implemented" + */ + stm->FEAT1R = (stm->FEAT1R & (~STMFEAT1_HWTEN)) | STMFEAT1_HWTEN_NOIMPL; + } + + /* Fix up Compression support */ + if ((stm->FEAT2R & STMFEAT2_SPCOMP) == STMFEAT2_SPCOMP_UNDEF) + { + /* + * COMPEN support is defined by the TCSR reacting to a write, + * so perform that test write and fix up stm->FEAT1R to reflect + * whether it's programmable or not.. + */ + stm->APB->STMTCSR = stm->APB->STMTCSR | STMTCSR_COMPEN; + if (stm->APB->STMTCSR & STMTCSR_COMPEN) + stm->FEAT2R = (stm->FEAT2R & (~STMFEAT2_SPCOMP)) | STMFEAT2_SPCOMP_OK; + } + + /* Fix up SPTER support */ + if ((stm->FEAT2R & STMFEAT2_SPTER) == STMFEAT2_SPTER_UNDEF) + { + /* + * Presence of STMSPTER is defined by STMSPTER reacting to + * a write -- test it and fix up stm->FEAT2R to reflect the + * result + */ + stm->APB->STMSPTER = 0xffffffff; + if (stm->APB->STMSPTER > 0) { + stm->FEAT2R = (stm->FEAT2R & (~STMFEAT2_SPTER)) | STMFEAT2_SPTER_OK; + } + } +} + +/* + * Platform code needs to allocate and fill in a struct STM + * with pointers to the base address for APB and AXI memory + * regions. + * + * See stm_retarget.c for usage of gSTM and fputc impl. + */ + +void stmInit(struct STM *stm, struct stmAPB *apb, struct stmAXI *axi) +{ + unsigned int tcsrflags; + unsigned int i; + + stm->APB = apb; + stm->AXI = axi; + + /* + * Toggle the Lock Access register and disable the STM + * for the time being + */ + + stmUnlock(stm); + stmDisable(stm); + stmWaitForIdle(stm); + + stmInitFeatures(stm); + + stmHEDisableEventsAll(stm); + stmHEDisable(stm); + + stmSetTimestampFrequency(stm, CONFIG_STM_TIMESTAMP_FREQUENCY); + stmTimestamping(stm, 1); + + stmSetSyncFrequency(stm, CONFIG_STM_SYNC_FREQUENCY); + stmSynchronization(stm, 1); + + stmCompression(stm, CONFIG_STM_USE_COMPRESSION); + +#if defined(CONFIG_STM_USE_TRACEID) + /* STM Architecture Spec v1.1 (IHI00054B) 2.3.10: + * ~~ + * To avoid trace stream corruption, the STM must be disabled with + * STMTCSR.EN == 0b0 and the STMTCSR.BUSY bit polled until it is 0b0 + * before STMTCSR.TRACEID is modified. + * ~~ + * We already disabled the STMTCSR.EN bit and stmWaitForIdle() will + * wait for STMTCSR.BUSY to be 0. + */ + stmWaitForIdle(stm); + stmTRACEID(stm, CONFIG_STM_USE_TRACEID); +#endif + + stmEnablePortsAll(stm); + + stmEnable(stm); +} + +void stmUninit(struct STM *stm) +{ + stmDisable(stm); + stmWaitForIdle(stm); + stmLock(stm); +} + +/* + * + * address = stmPortAddress(base, port, flags) + * + * If you want to access the stimulus ports without the stmAXI structure and + * without using the macros, then you can generate an offset address using + * stmPortAddress(). + * + * Flags is some combination of: + * + * GUARANTEED or INVARIANT + * MARKED + * TIMESTAMPED + * FLAG + * TRIGGER + * + * Guaranteed and invariant semantics are mutually exclusive so if you + * specify both, it defaults to guaranteed. + * + * As an example: + * + * Generate an address for Channel 0 TRIG_TS packet (implicitly non-data): + * + * address = stmPortAddress(AXI_BASE, 0, (TRIGGER | TIMESTAMPED)) + * + * Generate an address for Channel 5 FLAG_TS packet (implicitly non-data): + * + * address = stmPortAddress(AXI_BASE, 5, (FLAG | INVARIANT | TIMESTAMPED)) + * + * Generate an address for Channel 3 Dn packet with GUARANTEED semantics: + * + * address = stmPortAddress(AXI_BASE, 3, (GUARANTEED)) + * + * Generate an address for Channel 4 DnM_TS packet with GUARANTEED semantics: + * + * address = stmPortAddress(AXI_BASE, 4, (GUARANTEED | MARKED | TIMESTAMPED)) + * + * Obviously where data output is possible that depends on what you + * do with the address you get out.. + * + */ +unsigned long stmPortAddress(unsigned long base, unsigned int channel, unsigned int flags) +{ + /* + * We don't actually use this function but it is a nice example of + * how the different STM stimulus types map to a stimulus register + * address. Based on the way we want the stimulus to go out we can + * generate an address, which we can then write with an appropriate + * sized access to generate that 'sized' packet + * + * See 3.3 Address decoding in STM Architecture Spec v1.1 (IHI0054B) + */ + + unsigned long address = 0; + + /* + * STM extended stimulus port bits are a little backwards. + * + * Address bit [7] makes a packet Guaranteed if clear + * Invariant if set + * [4] makes a packet Marked if clear + * Unmarked if set + * [3] makes a packet Timestamped if clear + * Untimestamped if set + */ + + // if flags GUARANTEED or not INVARIANT + if ((flags & GUARANTEED) || !(flags & INVARIANT)) { + address &= ~__GUARANTEED; + } else { + // default to INVARIANT + address |= __GUARANTEED; + } + + if (flags & TIMESTAMPED) + address &= ~__TIMESTAMPED; + else + address |= __TIMESTAMPED; + + /* + * EXCEPT when: + * [6:5] determines if it's non-DATA (b11) + * [4] is TRIGGER (or nFLAG if you prefer) + * [7] and [3] retain their meaning as above + * + * we let the API deal with using DATA, TRIGGER or FLAG + * flag items in an intuitive manner + */ + + if ((flags & TRIGGER) || (flags & FLAG)) { + address |= __NONDATA; + if ((flags & TRIGGER) || !(flags & FLAG)) + address &= ~__TRIGGERnFLAG; + else if (flags & FLAG) + address |= __TRIGGERnFLAG; + } else { + if (flags & MARKED) + address &= ~__MARKED; + else + address |= __MARKED; + } + + return ((unsigned long) (base + (channel << 9) + address)); +} + +/* + * void stmSendString(stm, channel, string) + * + * We specifically write a byte to ensure that we get a D8 packet, + * although that limits the function to 8-bit encodings. + * + * It doesn't matter what we use for the last write (if we see + * a null character) -- G_FLAGTS has no data except the flag and + * the timestamp, so a 32-bit access will be just fine.. +*/ + +void stmSendString(struct STM *stm, unsigned int channel, const char *string) +{ + /* + * Send a string to the STM extended stimulus registers + * The first character goes out as D8M (Marker) packet + * The last character is followed by a Timestamp packet + * + * This is the Annex C example from the STPv2 spec + * + * For a retargeted example see stm_retarget.c + */ + struct stmAXI *axi = stm->AXI; + + int first = 1; + + while(*string != '\0') + { + /* + * If the character is a linefeed, then don't output + * it -- just reset our 'first' state to 1 so that + * the next character (the start of the next line) + * is marked + */ + if (*string == '\n') { + STM32(axi, channel, G_FLAGTS) = *string++; + first = 1; + } else { + /* + * Continue to output characters -- if it's the + * first character in a string, or just after a + * linefeed (handled above), mark it. + */ + if (first) { + STM8(axi, channel, G_DM) = (*string++); + first = 0; + } else { + STM8(axi, channel, G_D) = (*string++); + } + } + } + + /* + * Flag the end of the string + * + * Access size doesn't matter as we have no data for flag + * packets + */ + STM32(axi, channel, G_FLAGTS) = 0x0; +} + +int stm_fputc(struct STM *stm, int c, FILE *f) { + struct stmAXI *axi = stm->AXI; + STM8(axi, 0, G_D) = (char )c; + return 0; +} diff --git a/fast-models-examples/STM_Demo/SW_Test/stm.h b/fast-models-examples/STM_Demo/SW_Test/stm.h new file mode 100644 index 00000000..3275bb23 --- /dev/null +++ b/fast-models-examples/STM_Demo/SW_Test/stm.h @@ -0,0 +1,287 @@ +/* + * STM Example + * + * Copyright (c) 2015-2016 ARM, Inc. All rights reserved. + * + */ + +#if !defined(__STM_H) +#define __STM_H + +typedef unsigned int STM_RO; +typedef volatile STM_RO STM_RW; +typedef STM_RW STM_NA; +typedef volatile unsigned long STM_STIM; + +struct stmDMA; +struct stmHE; + +#define TRACEID_MASK (0x7f) +#define TRACEID_SHIFT (16) + +struct stmAPB { + STM_RW STMSTIMR[32]; + STM_NA RSVD_0[608]; + STM_NA IMPDEF[4][64]; + STM_RW STMSPER; + STM_NA RSVD_2[7]; + STM_RW STMSPTER; + STM_NA RSVD_3[7]; + STM_RW STMPRIVMASKR; + STM_NA RSVD_4[7]; + STM_RW STMSPSCR; + STM_RW STMSPMSCR; + STM_RW STMSPOVERRIDER; + STM_RW STMSPMOVERRIDER; + STM_RW STMSPTRIGCSR; + STM_NA RSVD_5[3]; + STM_RW STMTCSR; +#define STMTCSR_EN (1 << 0) +#define STMTCSR_TSEN (1 << 1) +#define STMTCSR_SYNCEN (1 << 2) +#define STMTCSR_HWTEN (1 << 3) +#define STMTCSR_COMPEN (1 << 5) +#define STMTCSR_BUSY (1 << 23) + STM_RW STMTSSTIMR; + STM_NA RSVD_6; + STM_RW STMTSFREQR; + STM_RW STMSYNCR; + STM_RW STMAUXCR; + STM_NA RSVD_7[2]; + STM_RO STMFEAT1R; +#define STMFEAT1_TS (1 << 4) +#define STMFEAT1_TS_DIFF (0 << 4) +#define STMFEAT1_TS_ABS (1 << 4) +#define STMFEAT1_TS_NOIMPL (2 << 4) +#define STMFEAT1_TS_RSVD (3 << 4) +#define STMFEAT1_TSFREQ (1 << 6) +#define STMFEAT1_FORCETS (1 << 7) +#define STMFEAT1_SYNCR (3 << 8) +#define STMFEAT1_SYNCR_UNDEF (0 << 0) +#define STMFEAT1_SYNCR_NOIMPL (1 << 8) +#define STMFEAT1_SYNCR_NOMODE (2 << 8) +#define STMFEAT1_SYNCR_OKMODE (3 << 8) +#define STMFEAT1_HWTEN (3 << 18) +#define STMFEAT1_HWTEN_UNDEF (0 << 18) +#define STMFEAT1_HWTEN_NOIMPL (1 << 18) +#define STMFEAT1_HWTEN_OK (2 << 18) +#define STMFEAT1_HWTEN_RSVD (3 << 18) +#define STMFEAT1_SYNCEN (3 << 20) +#define STMFEAT1_SYNCEN_UNDEF (0 << 20) +#define STMFEAT1_SYNCEN_NOIMPL (1 << 20) +#define STMFEAT1_SYNCEN_ALWAYS (2 << 20) +#define STMFEAT1_SYNCEN_OK (3 << 20) + STM_RO STMFEAT2R; +#define STMFEAT2_SPTER (3 << 0) +#define STMFEAT2_SPTER_UNDEF (0 << 0) +#define STMFEAT2_SPTER_NOIMPL (1 << 0) +#define STMFEAT2_SPTER_OK (2 << 0) +#define STMFEAT2_SPER (1 << 2) +#define STMFEAT2_SPER_OK (0 << 2) +#define STMFEAT2_SPER_NOIMPL (1 << 2) +#define STMFEAT2_SPCOMP (3 << 4) +#define STMFEAT2_SPCOMP_UNDEF (0 << 4) +#define STMFEAT2_SPCOMP_NOIMPL (1 << 4) +#define STMFEAT2_SPCOMP_ALWAYS (2 << 4) +#define STMFEAT2_SPCOMP_OK (3 << 4) + STM_RO STMFEAT3R; + STM_RO RSVD_8[15]; + union { + STM_NA RSVD[6]; + struct STM_IT { + STM_RW STMITTRIGGER; + STM_RW STMITATBDATA0; + STM_RW STMITATBCTR2; + STM_RW STMITATBID; + STM_RW STMITATBCTR0; + STM_NA RSVD; + } STMIT; + } RSVD_9; + STM_RW STMITCTRL; + STM_NA RSVD_A[39]; + STM_RW STMCLAIMSET; + STM_RW STMCLAIMCLR; + STM_NA RSVD_B[2]; + STM_RW STMLAR; +#define STMLAR_UNLOCK (0xc5acce55) +#define STMLAR_LOCK (0x00000000) + STM_RW STMLSR; +#define STMLSR_SLI (1 << 0) +#define STMLSR_SLK (1 << 1) + STM_RW STMAUTHSTATUS; + STM_RO STMDEVARCH; + STM_RO RSVD_C[2]; + STM_RO STMDEVID; + STM_RO STMDEVTYPE; + STM_RO STMPIDR[8]; + STM_RO STMCIDR[4]; +}; + +struct stmPort { + STM_STIM G_DMTS; + STM_STIM G_DM; + STM_STIM G_DTS; + STM_STIM G_D; + STM_NA G_reserved[16]; + + STM_STIM G_FLAGTS; + STM_STIM G_FLAG; + STM_STIM G_TRIGTS; + STM_STIM G_TRIG; + + STM_STIM I_DMTS; + STM_STIM I_DM; + STM_STIM I_DTS; + STM_STIM I_D; + STM_NA I_reserved[16]; + + STM_STIM I_FLAGTS; + STM_STIM I_FLAG; + STM_STIM I_TRIGTS; + STM_STIM I_TRIG; +}; + +/* Implementation defined controls from STM Architecture v1.1 */ + +struct stmDMA { + STM_NA RSVD_0; + STM_RW STMDMASTARTR; + STM_RW STMDMASTOPR; + STM_RW STMDMASTATR; + STM_RW STMDMACTLR; + STM_NA RSVD_1[58]; + STM_RW STMDMAIDR; +}; + +struct stmHE { + STM_RW STMHEERR; + STM_NA RSVD_0[7]; + STM_RW STMHETER; + STM_NA RSVD_1[15]; + STM_RW STMHEBSR; /* NOTE: not present in Standard HE v1.0 */ + STM_RW STMHEMCR; + STM_RW STMHEEXTMUXR; + STM_NA RSVD_2[34]; + STM_RW STMHEMASTR; + STM_RO STMHEFEAT1R; +#define STMHEFEAT1_HETER (1 << 0) +#define STMHEFEAT1_HEERR (1 << 2) +#define STMHEFEAT1_HECOMP (3 << 4) + STM_RO STMHEIDR; +}; + +/* + * STM AXI Stimulus Interface + * + * The STM Architecture defines up to 65536 stimulus ports, all of which are + * implemented on the STM and STM-500 from ARM, Ltd. + */ +struct stmAXI { + /* + * access the port array based on the limit in + * (stmAPB->STMDEVID & 0x1fff) so nothing we + * can define at compile time.. + */ + struct stmPort port[0]; +}; + +struct STM { + struct stmAPB *APB; + struct stmAXI *AXI; + + struct stmDMA *DMA; + struct stmHE *HE; + void *unused0; + void *unused1; + + /* Feature Register Cache */ + unsigned int DEVARCH; + unsigned int DEVID; + unsigned int FEAT1R; + unsigned int FEAT2R; + unsigned int FEAT3R; + unsigned int IMPDEFIDR[4]; + unsigned int HEFEAT1R; + + unsigned int NumPorts; + unsigned int DSize; +}; + +extern struct STM *gSTM; + +/* + * STMn(port, class) + * + * Write an n-byte value to a stimulus port of a particular type (e.g. G_DMTS) + */ +#define STM8(a, p, type) *((volatile unsigned char *) &((a)->port[p].type)) +#define STM16(a, p, type) *((volatile unsigned short *) &((a)->port[p].type)) +#define STM32(a, p, type) *((volatile unsigned int *) &((a)->port[p].type)) +#define STM64(a, p, type) *((volatile unsigned long *) &((a)->port[p].type)) + +/* + * unsigned long stmPortAddress(unsigned long base, unsigned int port, unsigned int flags) + * + * If you want to access the stimulus ports without the stmAXI structure and + * without using the above macros, then you can generate an offset address using + * stmPortAddress(). + * + * Flags that are also address bits + */ +#define __GUARANTEED (1 << 7) +#define __NONDATA (3 << 5) +#define __MARKED (1 << 4) +#define __TRIGGERnFLAG (1 << 4) +#define __TIMESTAMPED (1 << 3) + +/* + * these are ONLY flags not address bits + */ +#define INVARIANT (1 << 0) +#define FLAG (1 << 1) +#define TRIGGER (1 << 2) +#define TIMESTAMPED __TIMESTAMPED +#define MARKED __MARKED +#define GUARANTEED __GUARANTEED + +extern unsigned long stmPortAddress(unsigned long base, unsigned int port, unsigned int flags); +extern void stmInit(struct STM *stm, struct stmAPB *apb, struct stmAXI *axi); +extern void stmSendString(struct STM *stm, unsigned int channel, const char *string); + + +/* + * Required + * + * Timestamp frequency is more a hint to trace decoders + * than any functional change in the STM itself. It allows + * conversion of the output TS packets from raw binary + * to hh:mm:ss. + * + * The frequency of sync generation will be handled in + * hardware but its behaviour is somewhat undefined. By + * starting trace you will get an ASYNC packet, but we + * want it to be regular in case our output buffer wraps. + * + * By giving these values we get more predictable trace + * decode. + */ +# define CONFIG_STM_TIMESTAMP_FREQUENCY 100000000L +# define CONFIG_STM_SYNC_FREQUENCY 1024 + +/* + * Optional + * + * Compression is optional. + * + * Setting the Trace ID is *not* optional, but the + * responsibility of setting it could be to the software + * or an external debugger. Therefore, we only set the + * value if an external debugger is not going to do it + * for us. + */ +# define CONFIG_STM_USE_COMPRESSION 1 +# define CONFIG_STM_USE_TRACEID 16 + +int stm_fputc(struct STM *stm, int c, FILE *f); + +#endif /* !defined(__STM_H_) */