OpenCores
URL https://opencores.org/ocsvn/riscv_vhdl/riscv_vhdl/trunk

Subversion Repositories riscv_vhdl

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /riscv_vhdl/trunk/debugger
    from Rev 4 to Rev 5
    Reverse comparison

Rev 4 → Rev 5

/msvc13/arm7_plugin/arm7_plugin.vcxproj
0,0 → 1,200
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{1908ECA9-9686-43C7-822F-76FDE9992BAD}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>arm7_plugin</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\..\win32build\$(Configuration)\plugins\</OutDir>
<IntDir>$(SolutionDir)$(ProjectName)\$(Configuration)\Tmp\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<OutDir>$(SolutionDir)\..\win64build\$(Configuration)\plugins\</OutDir>
<IntDir>$(SolutionDir)$(ProjectName)\$(Configuration)\Tmp\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<OutDir>$(SolutionDir)\..\win32build\$(Configuration)\plugins\</OutDir>
<IntDir>$(SolutionDir)$(ProjectName)\$(Configuration)\Tmp\</IntDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)../src/common</AdditionalIncludeDirectories>
<AdditionalOptions>/vmg %(AdditionalOptions)</AdditionalOptions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libdbg64g.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\..\win32build\$(Configuration)\</AdditionalLibraryDirectories>
<ModuleDefinitionFile>$(ProjectDir)exportmap.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)../src/common</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>libdbg64g.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>$(SolutionDir)\..\win64build\$(Configuration)\</AdditionalLibraryDirectories>
<ModuleDefinitionFile>$(ProjectDir)exportmap.def</ModuleDefinitionFile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)../src/common;$(SolutionDir)../src/socsim_plugin/</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(SolutionDir)\..\win32build\$(Configuration)\</AdditionalLibraryDirectories>
<ModuleDefinitionFile>$(ProjectDir)exportmap.def</ModuleDefinitionFile>
<AdditionalDependencies>libdbg64g.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>$(SolutionDir)../src/common;$(SolutionDir)../src/socsim_plugin/</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalLibraryDirectories>$(SolutionDir)\..\bin\$(Configuration)\</AdditionalLibraryDirectories>
<ModuleDefinitionFile>$(ProjectDir)exportmap.def</ModuleDefinitionFile>
<AdditionalDependencies>libdbg64g.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\src\common\async_tqueue.cpp" />
<ClCompile Include="..\..\src\common\attribute.cpp" />
<ClCompile Include="..\..\src\common\autobuffer.cpp" />
<ClCompile Include="..\..\src\common\generic\cpu_generic.cpp" />
<ClCompile Include="..\..\src\common\generic\iotypes.cpp" />
<ClCompile Include="..\..\src\common\generic\mapreg.cpp" />
<ClCompile Include="..\..\src\cpu_arm_plugin\arm7tdmi.cpp" />
<ClCompile Include="..\..\src\cpu_arm_plugin\cpu_arm7_func.cpp" />
<ClCompile Include="..\..\src\cpu_arm_plugin\instructions.cpp" />
<ClCompile Include="..\..\src\cpu_arm_plugin\plugin_init.cpp" />
<ClCompile Include="..\..\src\cpu_arm_plugin\srcproc\srcproc.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\common\api_types.h" />
<ClInclude Include="..\..\src\common\api_utils.h" />
<ClInclude Include="..\..\src\common\async_tqueue.h" />
<ClInclude Include="..\..\src\common\attribute.h" />
<ClInclude Include="..\..\src\common\autobuffer.h" />
<ClInclude Include="..\..\src\common\coreservices\iclock.h" />
<ClInclude Include="..\..\src\common\coreservices\icpuarm.h" />
<ClInclude Include="..\..\src\common\generic\cpu_generic.h" />
<ClInclude Include="..\..\src\common\generic\iotypes.h" />
<ClInclude Include="..\..\src\common\generic\mapreg.h" />
<ClInclude Include="..\..\src\common\iattr.h" />
<ClInclude Include="..\..\src\common\iclass.h" />
<ClInclude Include="..\..\src\common\iface.h" />
<ClInclude Include="..\..\src\common\iservice.h" />
<ClInclude Include="..\..\src\cpu_arm_plugin\arm-isa.h" />
<ClInclude Include="..\..\src\cpu_arm_plugin\cpu_arm7_func.h" />
<ClInclude Include="..\..\src\cpu_arm_plugin\instructions.h" />
<ClInclude Include="..\..\src\cpu_arm_plugin\srcproc\srcproc.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
/msvc13/arm7_plugin/arm7_plugin.vcxproj.filters
0,0 → 1,111
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="common">
<UniqueIdentifier>{f5a16e1a-fd0c-436b-9f2e-d8942e1ccf15}</UniqueIdentifier>
</Filter>
<Filter Include="common\coreservices">
<UniqueIdentifier>{c38cf23f-4095-49ba-9e73-efe727a3c527}</UniqueIdentifier>
</Filter>
<Filter Include="src">
<UniqueIdentifier>{f72d2a1b-34ac-4ff6-b8b2-99c765d329d2}</UniqueIdentifier>
</Filter>
<Filter Include="src\srcproc">
<UniqueIdentifier>{59ced6ee-7796-4e40-bae3-95c7735fbe2f}</UniqueIdentifier>
</Filter>
<Filter Include="common\generic">
<UniqueIdentifier>{83001fb3-54a8-4519-8a30-b3a7dfeab4b6}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\src\common\attribute.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\src\common\autobuffer.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\src\common\async_tqueue.cpp">
<Filter>common</Filter>
</ClCompile>
<ClCompile Include="..\..\src\common\generic\mapreg.cpp">
<Filter>common\generic</Filter>
</ClCompile>
<ClCompile Include="..\..\src\common\generic\cpu_generic.cpp">
<Filter>common\generic</Filter>
</ClCompile>
<ClCompile Include="..\..\src\common\generic\iotypes.cpp">
<Filter>common\generic</Filter>
</ClCompile>
<ClCompile Include="..\..\src\cpu_arm_plugin\arm7tdmi.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\src\cpu_arm_plugin\cpu_arm7_func.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\src\cpu_arm_plugin\instructions.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\src\cpu_arm_plugin\plugin_init.cpp">
<Filter>src</Filter>
</ClCompile>
<ClCompile Include="..\..\src\cpu_arm_plugin\srcproc\srcproc.cpp">
<Filter>src\srcproc</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\..\src\common\api_types.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\api_utils.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\attribute.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\autobuffer.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\iattr.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\iclass.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\iface.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\iservice.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\async_tqueue.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\coreservices\iclock.h">
<Filter>common</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\generic\mapreg.h">
<Filter>common\generic</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\generic\cpu_generic.h">
<Filter>common\generic</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\generic\iotypes.h">
<Filter>common\generic</Filter>
</ClInclude>
<ClInclude Include="..\..\src\cpu_arm_plugin\cpu_arm7_func.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\src\cpu_arm_plugin\instructions.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\src\cpu_arm_plugin\arm-isa.h">
<Filter>src</Filter>
</ClInclude>
<ClInclude Include="..\..\src\common\coreservices\icpuarm.h">
<Filter>common\coreservices</Filter>
</ClInclude>
<ClInclude Include="..\..\src\cpu_arm_plugin\srcproc\srcproc.h">
<Filter>src\srcproc</Filter>
</ClInclude>
</ItemGroup>
</Project>
/msvc13/arm7_plugin/arm7_plugin.vcxproj.user
0,0 → 1,4
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>
/msvc13/arm7_plugin/exportmap.def
0,0 → 1,3
LIBRARY arm7_plugin
EXPORTS
plugin_init
/scripts/autotest1.py
0,0 → 1,18
"""
@copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
@author Sergey Khabarov - sergeykhbr@gmail.com
@brief Test automation procedure (functional model for now).
"""
 
import sys,rpc
pump = rpc.Simulator()
pump.connect()
 
pump.halt()
 
pump.step(3)
pump.go_msec(50.0)
pump.simSteps()
pump.simTimeSec()
 
pump.disconnect()
/scripts/rpc/__init__.py
0,0 → 1,163
"""
@copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
@author Sergey Khabarov - sergeykhbr@gmail.com
@brief Simulator's Python API implementation.
"""
 
import threading
import client
from events import ConsoleSubStringEvent
 
class Simulator(object):
def __init__(self):
self.client = None
self.eventDone = threading.Event()
 
def connect(self):
self.eventDone.clear()
self.client = client.TcpClient("rpcclient", self.eventDone)
self.client.start()
self.eventDone.wait()
 
def disconnect(self):
self.client.stop()
self.client.join()
 
def log(self, file):
req = ["Command","log {0}".format(file)]
return self.client.send(req)
def loadsrec(self, file):
req = ["Command","loadsrec {0}".format(file)]
return self.client.send(req)
 
def loadmap(self, file):
req = ["Command","loadmap {0}".format(file)]
return self.client.send(req)
 
def pressButton(self, btn):
req = ["Button",["Press",btn]]
return self.client.send(req)
 
def releaseButton(self, btn):
req = ["Button",["Release",btn]]
return self.client.send(req)
 
def clickButton(self, btn):
self.pressButton(btn)
self.go_msec(50.0)
self.releaseButton(btn)
self.go_msec(50.0)
 
def symb2addr(self, symb):
req = ["Symbol",["ToAddr",symb]]
return self.client.send(req)
 
def br_add(self, location):
req = ["Breakpoint",["Add",location]]
return self.client.send(req)
 
def br_rm(self, location):
req = ["Breakpoint",["Remove",location]]
return self.client.send(req)
 
def go(self):
req = ["Command","c"]
return self.client.send(req)
 
def go_until(self, location):
req = ["Control",["GoUntil",location]]
return self.client.send(req)
 
def go_msec(self, ms):
req = ["Control",["GoMsec",float(ms)]]
return self.client.send(req)
 
def go_substr(self, template, timeout=None):
"""
Run simulation until debug console output doesn't print string
containting 'template' substring or timeout happened.
In a case of timeout exception will be generated.
"""
ev1 = ConsoleSubStringEvent(template)
self.client.registerConsoleListener(ev1)
if not self.isON():
self.power_on()
elif self.isHalt():
self.go()
ev1.wait(timeout)
self.halt()
self.client.unregisterConsoleListener(ev1)
 
def halt(self):
req = ["Command","s"]
return self.client.send(req)
 
def step(self, count):
req = ["Control",["Step",count]]
return self.client.send(req)
 
def power_on(self):
req = ["Control",["PowerOn"]]
return self.client.send(req)
 
def power_off(self):
req = ["Control",["PowerOff"]]
return self.client.send(req)
 
def setSyringe(self, diam, k1, k2):
req = ["Syringe",[float(diam),k1,k2]]
return self.client.send(req)
 
def isON(self):
req = ["Status","IsON"]
return self.client.send(req)
 
def isHalt(self):
req = ["Status","IsHalt"]
return self.client.send(req)
 
def simSteps(self):
"""
Get simulated number of steps. One step equals to one CPU instruction.
"""
req = ["Status","Steps"]
return self.client.send(req)
 
def simTimeSec(self):
"""
Get simulated time in seconds. It's computed as number of steps
multiplied on Bus frequency in Hz.
"""
req = ["Status","TimeSec"]
return self.client.send(req)
 
def microphone(self, ena):
"""
Enable\Disable integrated microphone.
"""
req = ["Control",["Microphone",bool(ena)]]
return self.client.send(req)
 
def battery(self, voltage=None):
"""
Request battery level when voltage equals to None or
Change battery level in Volts
"""
if voltage:
req = ["Control",["Battery",float(voltage)]]
else:
req = ["Control",["Battery"]]
return self.client.send(req)
 
def getIndicator(self):
"""
Read state of the User's indicator
"""
req = ["Attribute",["userindicator","State"]]
resp = self.client.send(req)
if resp in [0,1,2,3]:
Colors = ["OFF", "RED", "GREEN", "YELLOW"]
return Colors[resp]
else:
return resp
/scripts/rpc/client.py
0,0 → 1,100
"""
@copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
@author Sergey Khabarov - sergeykhbr@gmail.com
@brief Transport TCP layer of the Python API.
"""
 
import threading
import socket
import time
from safe import safe_print
 
TCP_IP = '127.0.0.1'
TCP_PORT = 8687
BUFFER_SIZE = 1024
 
TCP_DEBUG = 1
 
class TcpClient(threading.Thread):
def __init__(self, name, eventDone):
threading.Thread.__init__(self)
self.name = name
self.skt = None
self.eventDone = eventDone
self.messageid = 0
self.enabled = True
self.eventTx = threading.Event()
self.response = ""
self.console_listeners = []
 
def run(self):
safe_print("Connecting to {0}:{1}\n".format(TCP_IP, TCP_PORT))
self.skt = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.skt.connect((TCP_IP, TCP_PORT))
self.eventDone.set()
 
buffer = ""
while self.enabled:
rxstr = self.skt.recv(BUFFER_SIZE)
if rxstr == '':
self.enabled = False
continue
 
buffer += rxstr
if '\0' in buffer:
strlist = buffer.split('\0')
if buffer.endswith('\0'):
buffer = ""
else:
buffer = strlist[len(strlist) - 1]
strlist = strlist[:-1]
 
for s in strlist:
if len(s) == 0:
continue
json = s.translate(None,'\n\r\0')
json = eval(json)
if TCP_DEBUG == 1:
safe_print("i<= {0}".format(json))
if json[0] == self.messageid:
self.messageid += 1
self.response = None
if len(json) > 1:
self.response = json[1]
self.eventTx.set()
elif json[0] == "Console":
for l in self.console_listeners:
l.callback(json[1])
else:
raise ValueError(
'Unexpected simulation response: {0}'.format(json))
else:
pass
 
# Ending of the thread:
safe_print("Thread {0} stopped".format(self.name))
 
def stop(self):
self.enabled = False
self.skt.shutdown(socket.SHUT_WR)
 
def send(self, data):
data.insert(0, self.messageid)
tx = bytearray(str(data))
tx.append(0)
if TCP_DEBUG == 1:
safe_print("o=> {0}".format(tx))
 
self.eventTx.clear()
self.response = ""
self.skt.send(tx)
self.eventTx.wait()
return self.response
 
def registerConsoleListener(self, listener):
self.console_listeners.append(listener)
 
def unregisterConsoleListener(self, listener):
if listener in self.console_listeners:
self.console_listeners.remove(listener)
/scripts/rpc/events.py
0,0 → 1,21
"""
@copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
@author Sergey Khabarov - sergeykhbr@gmail.com
@brief Simulator API asynchronous events implementation.
"""
 
import threading
 
class ConsoleSubStringEvent(object):
def __init__(self, template):
self.template = template
self.event = threading.Event()
self.event.clear()
 
def callback(self, s):
if self.template in s:
self.event.set()
 
def wait(self, sec=None):
if self.event.wait(sec) != True:
raise ValueError('ConsoleSubString timeout')
/scripts/rpc/safe.py
0,0 → 1,11
"""
@copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
@author Sergey Khabarov - sergeykhbr@gmail.com
@brief General thread safe methods.
"""
 
import sys
 
def safe_print(content):
#print "{0}".format(content)
sys.stdout.write(content + '\n')
/src/common/coreservices/icpu_hc08.h
0,0 → 1,86
/**
* @file
* @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved.
* @author Sergey Khabarov - sergeykhbr@gmail.com
* @brief CPU HC08 specific interface.
*/
 
#ifndef __DEBUGGER_COMMON_CORESERVICES_ICPU_HC08_H__
#define __DEBUGGER_COMMON_CORESERVICES_ICPU_HC08_H__
 
#include <inttypes.h>
#include <iface.h>
 
namespace debugger {
 
static const char *const IFACE_CPU_HC08 = "ICpuHC08";
 
enum ERegNames {
Reg_A, // 0
Reg_HX, // 1
Reg_SP, // 2
Reg_CCR, // 3
Reg_PPAGE, // 4
Reg_ClkHz, // 5
Reg_rsrv6, // 6
Reg_rsrv7,
Reg_rsrv8,
Reg_rsrv9,
Reg_rsrv10,
Reg_rsrv11,
Reg_rsrv12,
Reg_rsrv13,
Reg_rsrv14,
Reg_rsrv15,
Reg_rsrv16,
Reg_rsrv17,
Reg_rsrv18,
Reg_rsrv19,
Reg_rsrv20,
Reg_rsrv21,
Reg_rsrv22,
Reg_rsrv23,
Reg_rsrv24,
Reg_rsrv25,
Reg_rsrv26,
Reg_rsrv27,
Reg_rsrv28,
Reg_rsrv29,
Reg_rsrv30,
Reg_rsrv31,
Reg_Total
};
 
/** Signal types */
enum EResetType {
RESET_Unused0,
RESET_LVI, // Low-voltage inhibit Reset Bit
RESET_Unused2,
RESET_ILAD, // Illegal Address Reset Bit
RESET_ILOP, // Illegal Opcode Reset Bit
RESET_COP, // Compute Operating Properly Reset Bit
RESET_PIN, // External Reset Bit (nRST)
RESET_PON, // POWER-on Reset Bit
};
 
class ICpuHC08 : public IFace {
public:
ICpuHC08() : IFace(IFACE_CPU_HC08) {}
 
/** Fast access to memory mapped registers */
virtual Reg64Type *getpRegs() = 0;
 
/** External IRQ line status (need for BIH, BIL instructions) */
virtual bool getIRQ() = 0;
 
/** Update COP watchdog settings */
virtual void updateCOP() = 0;
 
/** Reset sequence has ben writen */
virtual void resetCOP() = 0;
virtual void vectorUpdated() = 0;
};
 
} // namespace debugger
 
#endif // __DEBUGGER_COMMON_CORESERVICES_ICPU_HC08_H__
src/common/coreservices/icpu_hc08.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/icpuarm.h =================================================================== --- src/common/coreservices/icpuarm.h (nonexistent) +++ src/common/coreservices/icpuarm.h (revision 5) @@ -0,0 +1,75 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEBUGGER_SRC_COMMON_CORESERVICES_ICPUARM_H__ +#define __DEBUGGER_SRC_COMMON_CORESERVICES_ICPUARM_H__ + +#include "iface.h" +#include + +namespace debugger { + +static const char *const IFACE_CPU_ARM = "ICpuArm"; + +/** Signal types */ +//static const int CPU_SIGNAL_RESET = 0; +//static const int CPU_SIGNAL_EXT_IRQ = 1; + +enum EInstructionModes { + ARM_mode, + THUMB_mode, + Jazelle_mode, + InstrModes_Total = 4 +}; + +enum ECoreModes { + User_mode = 0x10, + FIQ_mode = 0x11, + IRQ_mode = 0x12, + Supervisor_mode = 0x13, + Abort_mode = 0x17, + Undefined_mode = 0x1B, + System_mode = 0x1F, + CoreModes_Total = 32 +}; + +class ICpuArm : public IFace { + public: + ICpuArm() : IFace(IFACE_CPU_ARM) {} + + virtual void setInstrMode(EInstructionModes mode) {} + virtual EInstructionModes getInstrMode() { return ARM_mode; } + + /** Zero flag */ + virtual uint32_t getZ() = 0; + virtual void setZ(uint32_t z) = 0; + + /** Unsigned higer or same (carry flag) */ + virtual uint32_t getC() = 0; + virtual void setC(uint32_t c) = 0; + + /** Negative flag */ + virtual uint32_t getN() = 0; + virtual void setN(uint32_t n) = 0; + + /** Overflow flag */ + virtual uint32_t getV() = 0; + virtual void setV(uint32_t v) = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_SRC_COMMON_CORESERVICES_ICPUARM_H__
src/common/coreservices/icpuarm.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/icpufunctional.h =================================================================== --- src/common/coreservices/icpufunctional.h (nonexistent) +++ src/common/coreservices/icpufunctional.h (revision 5) @@ -0,0 +1,79 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Functional CPU model interface. + */ + +#ifndef __DEBUGGER_COMMON_CORESERVICES_ICPUFUNCTIONAL_H__ +#define __DEBUGGER_COMMON_CORESERVICES_ICPUFUNCTIONAL_H__ + +#include +#include +#include +#include "coreservices/imemop.h" + +namespace debugger { + +static const char *const IFACE_INSTRUCTION = "IInstruction"; + +class IInstruction : public IFace { + public: + IInstruction() : IFace(IFACE_INSTRUCTION) {} + + virtual const char *name() = 0; + /** Return instruction size */ + virtual int exec(Reg64Type *payload) = 0; +}; + +class GenericInstruction : public IInstruction { + public: + GenericInstruction() : IInstruction() {} +}; + +enum EEndianessType { + LittleEndian, + BigEndian, +}; + +static const char *const IFACE_CPU_FUNCTIONAL = "ICpuFunctional"; + +class ICpuFunctional : public IFace { + public: + ICpuFunctional() : IFace(IFACE_CPU_FUNCTIONAL) {} + + virtual void raiseSoftwareIrq() = 0; + virtual uint64_t getPC() = 0; + virtual void setBranch(uint64_t npc) = 0; + virtual void pushStackTrace() = 0; + virtual void popStackTrace() = 0; + virtual uint64_t getPrvLevel() = 0; + virtual void setPrvLevel(uint64_t lvl) = 0; + virtual void dma_memop(Axi4TransactionType *tr) = 0; + virtual bool isOn() = 0; + virtual bool isHalt() = 0; + virtual bool isSwBreakpoint() = 0; + virtual bool isHwBreakpoint() = 0; + virtual void go() = 0; + virtual void halt(const char *descr) = 0; + virtual void step() = 0; + virtual void addHwBreakpoint(uint64_t addr) = 0; + virtual void removeHwBreakpoint(uint64_t addr) = 0; + virtual void skipBreakpoint() = 0; + + protected: + virtual uint64_t getResetAddress() = 0; + virtual uint64_t getIrqAddress(int idx) = 0; + virtual EEndianessType endianess() = 0; + virtual GenericInstruction *decodeInstruction(Reg64Type *cache) = 0; + virtual void generateIllegalOpcode() = 0; + virtual void handleTrap() = 0; + /** Tack Registers changes during execution */ + virtual void trackContextStart() = 0; + /** Stop tracking and write trace file */ + virtual void trackContextEnd() = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_CORESERVICES_ICPUFUNCTIONAL_H__
src/common/coreservices/icpufunctional.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/icpugen.h =================================================================== --- src/common/coreservices/icpugen.h (nonexistent) +++ src/common/coreservices/icpugen.h (revision 5) @@ -0,0 +1,50 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Generic CPU simulating interface. + */ + +#ifndef __DEBUGGER_COMMON_CORESERVICES_ICPUGEN_H__ +#define __DEBUGGER_COMMON_CORESERVICES_ICPUGEN_H__ + +#include +#include +#include "coreservices/imemop.h" + +namespace debugger { + +static const char *const IFACE_CPU_GENERIC = "ICpuGeneric"; +static const uint64_t REG_INVALID = ~0; + +struct DebugPortTransactionType { + bool write; + uint8_t region; + uint16_t addr; + uint32_t bytes; + uint64_t wdata; + uint64_t rdata; +}; + +static const char *const IFACE_DBG_NB_RESPONSE = "IDbgNbResponse"; + +class IDbgNbResponse : public IFace { + public: + IDbgNbResponse() : IFace(IFACE_DBG_NB_RESPONSE) {} + + virtual void nb_response_debug_port(DebugPortTransactionType *trans) = 0; +}; + +class ICpuGeneric : public IFace { + public: + ICpuGeneric() : IFace(IFACE_CPU_GENERIC) {} + + virtual void raiseSignal(int idx) = 0; + virtual void lowerSignal(int idx) = 0; + virtual void nb_transport_debug_port(DebugPortTransactionType *trans, + IDbgNbResponse *cb) = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_CORESERVICES_ICPUGEN_H__
src/common/coreservices/icpugen.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/idisplay.h =================================================================== --- src/common/coreservices/idisplay.h (nonexistent) +++ src/common/coreservices/idisplay.h (revision 5) @@ -0,0 +1,40 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Dismplay Simulation interface. + */ + +#ifndef __DEBUGGER_PLUGIN_IDISPLAY_H__ +#define __DEBUGGER_PLUGIN_IDISPLAY_H__ + +#include +#include + +namespace debugger { + +static const char *const IFACE_DISPLAY = "IDisplay"; + +class IDisplay : public IFace { + public: + IDisplay() : IFace(IFACE_DISPLAY) {} + + virtual void initFrame() = 0; + virtual void setFramePixel(int x, int y, uint32_t rgb) = 0; + virtual void updateFrame() = 0; +}; + +static const char *const IFACE_LED_CONTROLLER = "ILedController"; + +class ILedController : public IFace { + public: + ILedController() : IFace(IFACE_LED_CONTROLLER) {} + + virtual void getResolution(int *width, int *height) = 0; + virtual void registerDisplay(IDisplay *led) = 0; + virtual void unregisterDisplay(IDisplay *led) = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_PLUGIN_IDISPLAY_H__
src/common/coreservices/idisplay.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/idsugen.h =================================================================== --- src/common/coreservices/idsugen.h (nonexistent) +++ src/common/coreservices/idsugen.h (revision 5) @@ -0,0 +1,29 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Generic Debug Support Unit simulating interface. + */ + +#ifndef __DEBUGGER_COMMON_CORESERVICES_IDSUGEN_H__ +#define __DEBUGGER_COMMON_CORESERVICES_IDSUGEN_H__ + +#include +#include + +namespace debugger { + +static const char *const IFACE_DSU_GENERIC = "IDsuGeneric"; + +class IDsuGeneric : public IFace { + public: + IDsuGeneric() : IFace(IFACE_DSU_GENERIC) {} + + /** Bus utilization statistic methods */ + virtual void incrementRdAccess(int mst_id) = 0; + virtual void incrementWrAccess(int mst_id) = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_CORESERVICES_ICPUGEN_H__
src/common/coreservices/idsugen.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/iencoder.h =================================================================== --- src/common/coreservices/iencoder.h (nonexistent) +++ src/common/coreservices/iencoder.h (revision 5) @@ -0,0 +1,31 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Optical Encoder interface. + */ + +#ifndef __DEBUGGER_COMMON_CORESERVICES_IENCODER_H__ +#define __DEBUGGER_COMMON_CORESERVICES_IENCODER_H__ + +#include +#include + +namespace debugger { + +static const char *const IFACE_ENCODER = "IEncoder"; + +class IEncoder : public IFace { + public: + IEncoder() : IFace(IFACE_ENCODER) {} + + virtual void rotateOn(int steps) = 0; + virtual uint8_t getEncoderState() = 0; + virtual double getAngleDegrees() = 0; + virtual double getHoles() = 0; + virtual double getPeriods() = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_CORESERVICES_IENCODER_H__
src/common/coreservices/iencoder.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/ii2c.h =================================================================== --- src/common/coreservices/ii2c.h (nonexistent) +++ src/common/coreservices/ii2c.h (revision 5) @@ -0,0 +1,46 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief I2C interface description. + */ + +#ifndef __DEBUGGER_COMMON_CORESERVICES_II2C_H__ +#define __DEBUGGER_COMMON_CORESERVICES_II2C_H__ + +#include +#include + +namespace debugger { + +enum EStatusI2C { + I2C_ACK = 0, + I2C_NACK = 1 +}; + +static const char *const IFACE_I2C_MASTER = "IMasterI2C"; + +class IMasterI2C : public IFace { + public: + IMasterI2C() : IFace(IFACE_I2C_MASTER) {} + + virtual void registerI2CListener(IFace *iface) = 0; + virtual void unregisterI2CListener(IFace *iface) = 0; +}; + +static const char *const IFACE_I2C_SLAVE = "ISlaveI2C"; + +class ISlaveI2C : public IFace { + public: + ISlaveI2C() : IFace(IFACE_I2C_SLAVE) {} + + virtual uint8_t getPhysAddress() = 0; + virtual uint8_t getAddressLen() = 0; + virtual void setAddress(uint32_t addr) = 0; + virtual EStatusI2C writeNext(uint8_t byte) = 0; + virtual EStatusI2C readNext(uint8_t *byte) = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_CORESERVICES_II2C_H__
src/common/coreservices/ii2c.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/iioport.h =================================================================== --- src/common/coreservices/iioport.h (nonexistent) +++ src/common/coreservices/iioport.h (revision 5) @@ -0,0 +1,38 @@ +/** + * @file + * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief IO-port interface declaration. + */ + +#ifndef __DEBUGGER_COMMON_CORESERVICES_IIOPORT_H__ +#define __DEBUGGER_COMMON_CORESERVICES_IIOPORT_H__ + +#include + +namespace debugger { + +static const char *IFACE_IOPORT = "IIOPort"; + +class IIOPort : public IFace { + public: + IIOPort() : IFace(IFACE_IOPORT) {} + + virtual void registerPortListener(IFace *listener) = 0; + virtual void unregisterPortListener(IFace *listener) = 0; +}; + +static const char *IFACE_IOPORT_LISTENER = "IIOPortListener"; + +class IIOPortListener : public IFace { + public: + IIOPortListener() : IFace(IFACE_IOPORT_LISTENER) {} + + virtual void readData(uint8_t *val, uint8_t mask) = 0; + virtual void writeData(uint8_t val, uint8_t mask) = 0; + virtual void latch() = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_CORESERVICES_IIOPORT_H__
src/common/coreservices/iioport.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/ikeyboard.h =================================================================== --- src/common/coreservices/ikeyboard.h (nonexistent) +++ src/common/coreservices/ikeyboard.h (revision 5) @@ -0,0 +1,28 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Keyboard interface declaration. + */ + +#ifndef __DEBUGGER_COMMON_CORESERVICES_IKEYBOARD_H__ +#define __DEBUGGER_COMMON_CORESERVICES_IKEYBOARD_H__ + +#include +#include + +namespace debugger { + +static const char *const IFACE_KEYBOARD = "IKeyboard"; + +class IKeyboard : public IFace { + public: + IKeyboard() : IFace(IFACE_KEYBOARD) {} + + virtual void keyPress(const char *keyname) = 0; + virtual void keyRelease(const char *keyname) = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_CORESERVICES_IKEYBOARD_H__
src/common/coreservices/ikeyboard.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/ilink.h =================================================================== --- src/common/coreservices/ilink.h (nonexistent) +++ src/common/coreservices/ilink.h (revision 5) @@ -0,0 +1,38 @@ +/** + * @file + * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Link interface declaration. + */ + +#ifndef __DEBUGGER_COMMON_CORESERVICES_ILINK_H__ +#define __DEBUGGER_COMMON_CORESERVICES_ILINK_H__ + +#include +#include +#include "irawlistener.h" + +namespace debugger { + +static const char *const IFACE_LINK = "ILink"; + +class ILink : public IFace { + public: + ILink() : IFace(IFACE_LINK) {} + + /** Get opened socket connection settings. */ + virtual void getConnectionSettings(AttributeType *settings) = 0; + + /** Setup remote host settings */ + virtual void setConnectionSettings(const AttributeType *target) = 0; + + /** Send datagram buffer. */ + virtual int sendData(const uint8_t *msg, int len) = 0; + + /** Read datagram buffer. */ + virtual int readData(const uint8_t *buf, int maxlen) = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_CORESERVICES_ILINK_H__
src/common/coreservices/ilink.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/immu.h =================================================================== --- src/common/coreservices/immu.h (nonexistent) +++ src/common/coreservices/immu.h (revision 5) @@ -0,0 +1,28 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief HC08 MMU interface. + */ + +#ifndef __DEBUGGER_COMMON_CORESERVICES_IMMU_H__ +#define __DEBUGGER_COMMON_CORESERVICES_IMMU_H__ + +#include +#include + +namespace debugger { + +static const char *const IFACE_MMU = "IMMU"; + +class IMMU : public IFace { + public: + IMMU() : IFace(IFACE_MMU) {} + + virtual uint32_t get_ppage() = 0; + virtual void set_ppage(uint8_t v) = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_CORESERVICES_IMMU_H__
src/common/coreservices/immu.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/imotor.h =================================================================== --- src/common/coreservices/imotor.h (nonexistent) +++ src/common/coreservices/imotor.h (revision 5) @@ -0,0 +1,40 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Motor with sensors interface. + */ + +#ifndef __DEBUGGER_PLUGIN_IMOTOR_H__ +#define __DEBUGGER_PLUGIN_IMOTOR_H__ + +#include +#include + +namespace debugger { + +static const char *const IFACE_MOTOR = "IMotor"; + +class IMotor : public IFace { + public: + IMotor() : IFace(IFACE_MOTOR) {} + + /** 0 = motor is stopped; 1.0 = maximum rpm and enabled Breaks */ + virtual double getPowerConsumption() = 0; + + /** Backward pressure: 1.0 = 100% oclusion; 0 = no backward pressure */ + virtual double getForceResistance() = 0; + virtual void changeForceResistance(double v) = 0; + + /** value in a range 0 to length mm */ + virtual double getActuatorPos() = 0; + virtual double getActuatorMax() = 0; + + // Debug methods: + virtual double getVelocity() = 0; + virtual double getCurrent() = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_PLUGIN_IMOTOR_H__
src/common/coreservices/imotor.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/ipll.h =================================================================== --- src/common/coreservices/ipll.h (nonexistent) +++ src/common/coreservices/ipll.h (revision 5) @@ -0,0 +1,27 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief PLL interface. + */ + +#ifndef __DEBUGGER_COMMON_CORESERVICES_IPLL_H__ +#define __DEBUGGER_COMMON_CORESERVICES_IPLL_H__ + +#include +#include + +namespace debugger { + +static const char *const IFACE_PLL = "IPLL"; + +class IPLL : public IFace { + public: + IPLL() : IFace(IFACE_PLL) {} + + virtual uint64_t getBusClockHz() = 0; +}; + +} // namespace debugger + +#endif // __DEBUGGER_PLUGIN_IPLL_H__
src/common/coreservices/ipll.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/ireset.h =================================================================== --- src/common/coreservices/ireset.h (nonexistent) +++ src/common/coreservices/ireset.h (revision 5) @@ -0,0 +1,66 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Generic reset interface. + */ + +#ifndef __DEBUGGER_PLUGIN_IRESET_H__ +#define __DEBUGGER_PLUGIN_IRESET_H__ + +#include +#include +#include + +namespace debugger { + +static const char *IFACE_RESET_LISTENER = "IResetListener"; + +class IResetListener : public IFace { + public: + IResetListener() : IFace(IFACE_RESET_LISTENER) {} + + virtual void reset(bool active) = 0; +}; + +static const char *const IFACE_RESET = "IReset"; + +class IReset : public IFace { + public: + IReset() : IFace(IFACE_RESET) { + resetListeners_.make_list(0); + } + + virtual void registerResetListener(IFace *listener) { + AttributeType item; + item.make_iface(listener); + resetListeners_.add_to_list(&item); + } + + virtual void unregisterResetListener(IFace *listener) { + for (unsigned i = 0; i < resetListeners_.size(); i++) { + if (listener == resetListeners_[i].to_iface()) { + resetListeners_.remove_from_list(i); + return; + } + } + } + + void reset(bool active) { + IResetListener *l; + for (unsigned i = 0; i < resetListeners_.size(); i++) { + l = static_cast(resetListeners_[i].to_iface()); + l->reset(active); + } + } + + virtual void powerOnPressed() = 0; + virtual void powerOnReleased() = 0; + + protected: + AttributeType resetListeners_; +}; + +} // namespace debugger + +#endif // __DEBUGGER_PLUGIN_IRESET_H__
src/common/coreservices/ireset.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/isensor.h =================================================================== --- src/common/coreservices/isensor.h (nonexistent) +++ src/common/coreservices/isensor.h (revision 5) @@ -0,0 +1,31 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Sensor's interface. + */ + +#ifndef __DEBUGGER_PLUGIN_ISENSOR_H__ +#define __DEBUGGER_PLUGIN_ISENSOR_H__ + +#include +#include + +namespace debugger { + +static const char *const IFACE_SENSOR = "ISensor"; + +class ISensor : public IFace { + public: + ISensor() : IFace(IFACE_SENSOR) {} + + virtual void changeSensorValue(double rate) = 0; + virtual double getSensorValue() = 0; + virtual double getPhysicalValue() { + return getSensorValue(); + } +}; + +} // namespace debugger + +#endif // __DEBUGGER_PLUGIN_ISENSOR_H__
src/common/coreservices/isensor.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/coreservices/isound.h =================================================================== --- src/common/coreservices/isound.h (nonexistent) +++ src/common/coreservices/isound.h (revision 5) @@ -0,0 +1,55 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Sound source interface with wav-format suppport. + */ + +#ifndef __DEBUGGER_COMMON_CORESERVICES_ISOUND_H__ +#define __DEBUGGER_COMMON_CORESERVICES_ISOUND_H__ + +#include +#include +#include + +namespace debugger { + +static const char *const IFACE_SOUND = "ISound"; + +static const int SOUND_CHANNELS_MAX = 2; + +struct SoundSampleType { + int chan[SOUND_CHANNELS_MAX]; +}; + +class ISound : public IFace { + public: + ISound() : IFace(IFACE_SOUND) { + soundListeners_.make_list(0); + } + + /** Update listeners with configurable bit rate 44.1 kHz for an example */ + virtual void registerSoundListener(IFace *listener) { + AttributeType item; + item.make_iface(listener); + soundListeners_.add_to_list(&item); + } + + virtual void unregisterSoundListener(IFace *listener) { + for (unsigned i = 0; i < soundListeners_.size(); i++) { + if (listener == soundListeners_[i].to_iface()) { + soundListeners_.remove_from_list(i); + return; + } + } + } + + virtual double getFreqDetectedHz() = 0; + + protected: + AttributeType soundListeners_; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_CORESERVICES_ISOUND_H__
src/common/coreservices/isound.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/debug/debugmap.h =================================================================== --- src/common/debug/debugmap.h (nonexistent) +++ src/common/debug/debugmap.h (revision 5) @@ -0,0 +1,35 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Debug Support Unit (DSU) memory map. + */ + +#ifndef __DEBUGGER_COMMON_DEBUG_DEBUGMAP_H__ +#define __DEBUGGER_COMMON_DEBUG_DEBUGMAP_H__ + +#include + +namespace debugger { + +union GenericCpuControlType { + uint64_t val; + struct { + uint64_t halt : 1; + uint64_t stepping : 1; + uint64_t sw_breakpoint : 1; + uint64_t hw_breakpoint : 1; + uint64_t core_id : 16; + uint64_t rsv2 : 12; + uint64_t istate : 2; // [33:32] icache state + uint64_t rsv3 : 2; // [35:34] + uint64_t dstate : 2; // [37:36] dcache state + uint64_t rsv4 : 2; // [39:38] + uint64_t cstate : 2; // [41:40] cachetop state + uint64_t rsv5 : 22; + } bits; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_DEBUG_DEBUGMAP_H__
src/common/debug/debugmap.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/debug/dsu.cpp =================================================================== --- src/common/debug/dsu.cpp (nonexistent) +++ src/common/debug/dsu.cpp (revision 5) @@ -0,0 +1,168 @@ +/** + * @file + * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Debug Support Unit (DSU) functional model. + */ + +#include +#include "dsu.h" + +namespace debugger { + +DSU::DSU(const char *name) : IService(name) { + registerInterface(static_cast(this)); + registerInterface(static_cast(this)); + registerInterface(static_cast(this)); + registerAttribute("CPU", &cpu_); + registerAttribute("Bus", &bus_); + + memset(&info_, 0, sizeof(info_)); + soft_reset_ = 0x0; // Active LOW +} + +DSU::~DSU() { +} + +void DSU::postinitService() { + icpu_ = static_cast( + RISCV_get_service_iface(cpu_.to_string(), IFACE_CPU_GENERIC)); + if (!icpu_) { + RISCV_error("Can't find ICpuGeneric interface %s", cpu_.to_string()); + } + icpurst_ = static_cast( + RISCV_get_service_iface(cpu_.to_string(), IFACE_RESET_LISTENER)); + if (!icpurst_) { + RISCV_error("Can't find IResetListener interface %s", + cpu_.to_string()); + } + ibus_ = static_cast( + RISCV_get_service_iface(bus_.to_string(), IFACE_MEMORY_OPERATION)); + if (!ibus_) { + RISCV_error("Can't find IBus interface %s", bus_.to_string()); + } +} + +ETransStatus DSU::b_transport(Axi4TransactionType *trans) { + uint64_t mask = (length_.to_uint64() - 1); + uint64_t off64 = (trans->addr - getBaseAddress()) & mask; + if (!icpu_) { + trans->response = MemResp_Error; + return TRANS_ERROR; + } + uint64_t region = (off64 >> 15) & 0x3; + + if (region < 3) { + RISCV_error("b_transport() to debug port NOT SUPPORTED", NULL); + trans->response = MemResp_Error; + return TRANS_ERROR; + } + + if (trans->action == MemAction_Read) { + readLocal(off64 & 0x7fff, trans); + } else { + writeLocal(off64 & 0x7fff, trans); + } + + trans->response = MemResp_Valid; + // @todo Memory mapped registers not related to debug port + return TRANS_OK; +} + +ETransStatus DSU::nb_transport(Axi4TransactionType *trans, + IAxi4NbResponse *cb) { + uint64_t mask = (length_.to_uint64() - 1); + uint64_t off64 = (trans->addr - getBaseAddress()) & mask; + if (!icpu_) { + trans->response = MemResp_Error; + cb->nb_response(trans); + return TRANS_ERROR; + } + + nb_trans_.p_axi_trans = trans; + nb_trans_.iaxi_cb = cb; + + nb_trans_.dbg_trans.write = 0; + nb_trans_.dbg_trans.bytes = trans->xsize; + if (trans->action == MemAction_Write) { + nb_trans_.dbg_trans.write = 1; + nb_trans_.dbg_trans.wdata = trans->wpayload.b64[0]; + } + + ETransStatus ret = TRANS_OK; + nb_trans_.dbg_trans.addr = off64 & 0x7FFF; + nb_trans_.dbg_trans.region = (off64 >> 15) & 0x3; + if (nb_trans_.dbg_trans.region == 3) { + ret = b_transport(trans); + cb->nb_response(trans); + } else { + icpu_->nb_transport_debug_port(&nb_trans_.dbg_trans, this); + } + return ret; +} + +void DSU::nb_response_debug_port(DebugPortTransactionType *trans) { + nb_trans_.p_axi_trans->response = MemResp_Valid; + nb_trans_.p_axi_trans->rpayload.b64[0] = trans->rdata; + nb_trans_.iaxi_cb->nb_response(nb_trans_.p_axi_trans); +} + +void DSU::readLocal(uint64_t off, Axi4TransactionType *trans) { + switch (off >> 3) { + case 0: + trans->rpayload.b64[0] = soft_reset_; + break; + case 8: + trans->rpayload.b64[0] = info_[0].w_cnt; + break; + case 9: + trans->rpayload.b64[0] = info_[0].r_cnt; + break; + case 12: + trans->rpayload.b64[0] = info_[2].w_cnt; + break; + case 13: + trans->rpayload.b64[0] = info_[2].r_cnt; + break; + default: + trans->rpayload.b64[0] = 0; + } + if (trans->xsize == 4 && (off & 0x4) == 0x4) { + trans->rpayload.b64[0] >>= 32; + } +} + +void DSU::writeLocal(uint64_t off, Axi4TransactionType *trans) { + if (trans->xsize == 4) { + if ((off & 0x4) == 0) { + wdata64_ = trans->wpayload.b32[0]; + return; + } else { + wdata64_ |= static_cast(trans->wpayload.b32[0]) << 32; + } + } else { + wdata64_ = trans->wpayload.b64[0]; + } + switch (off >> 3) { + case 0: // soft reset + if (wdata64_ & 0x1) { + icpurst_->reset(true); + } else { + icpurst_->reset(false); + } + soft_reset_ = wdata64_; + break; + default:; + } +} + +void DSU::incrementRdAccess(int mst_id) { + info_[mst_id].r_cnt++; +} + +void DSU::incrementWrAccess(int mst_id) { + info_[mst_id].w_cnt++; +} + +} // namespace debugger +
src/common/debug/dsu.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/common/debug/dsu.h =================================================================== --- src/common/debug/dsu.h (nonexistent) +++ src/common/debug/dsu.h (revision 5) @@ -0,0 +1,79 @@ +/** + * @file + * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Debug Support Unit (DSU) functional model. + * + * @details DSU supports both types of transaction: blocking and + * non-blocking it allows to interact with SystemC in the + * same manner as with the Functional model. + * @note CPU Functional model must implement non-blocking interface + */ + +#ifndef __DEBUGGER_COMMON_DEBUG_DSU_H__ +#define __DEBUGGER_COMMON_DEBUG_DSU_H__ + +#include +#include +#include "coreservices/imemop.h" +#include "coreservices/ireset.h" +#include "coreservices/icpugen.h" +#include "coreservices/idsugen.h" + +namespace debugger { + +class DSU : public IService, + public IMemoryOperation, + public IDbgNbResponse, + public IDsuGeneric { + public: + explicit DSU(const char *name); + ~DSU(); + + /** IService interface */ + virtual void postinitService(); + + /** IMemoryOperation */ + virtual ETransStatus b_transport(Axi4TransactionType *trans); + virtual ETransStatus nb_transport(Axi4TransactionType *trans, + IAxi4NbResponse *cb); + + /** IDbgNbResponse */ + virtual void nb_response_debug_port(DebugPortTransactionType *trans); + + /** IDsuGeneric */ + virtual void incrementRdAccess(int mst_id); + virtual void incrementWrAccess(int mst_id); + + private: + void readLocal(uint64_t off, Axi4TransactionType *trans); + void writeLocal(uint64_t off, Axi4TransactionType *trans); + + private: + AttributeType cpu_; + AttributeType bus_; + ICpuGeneric *icpu_; + IResetListener *icpurst_; + IMemoryOperation *ibus_; + uint64_t shifter32_; + uint64_t wdata64_; + uint64_t soft_reset_; + + struct nb_trans_type { + Axi4TransactionType *p_axi_trans; + IAxi4NbResponse *iaxi_cb; + DebugPortTransactionType dbg_trans; + } nb_trans_; + + static const int BUS_MASTERS_MAX = 64; + struct BusUtilType { + uint64_t w_cnt; + uint64_t r_cnt; + } info_[BUS_MASTERS_MAX]; +}; + +DECLARE_CLASS(DSU) + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_DEBUG_DSU_H__
src/common/debug/dsu.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/debug/greth.cpp =================================================================== --- src/common/debug/greth.cpp (nonexistent) +++ src/common/debug/greth.cpp (revision 5) @@ -0,0 +1,168 @@ +/** + * @file + * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Ethernet MAC device functional model. + */ + +#include +#include "greth.h" +#include "coreservices/isocinfo.h" + +namespace debugger { + +/** Class registration in the Core */ +REGISTER_CLASS(Greth) + +Greth::Greth(const char *name) + : IService(name) { + registerInterface(static_cast(this)); + registerInterface(static_cast(this)); + registerInterface(static_cast(this)); + registerAttribute("IP", &ip_); + registerAttribute("MAC", &mac_); + registerAttribute("Bus", &bus_); + registerAttribute("Transport", &transport_); + registerAttribute("SysBusMasterID", &sysBusMasterID_); + + memset(txbuf_, 0, sizeof(txbuf_)); + seq_cnt_ = 35; + RISCV_event_create(&event_tap_, "UART_event_tap"); +} +Greth::~Greth() { + RISCV_event_close(&event_tap_); +} + +void Greth::postinitService() { + ibus_ = static_cast( + RISCV_get_service_iface(bus_.to_string(), IFACE_MEMORY_OPERATION)); + + if (!ibus_) { + RISCV_error("Bus interface '%s' not found", + bus_.to_string()); + return; + } + + itransport_ = static_cast( + RISCV_get_service_iface(transport_.to_string(), IFACE_LINK)); + + if (!itransport_) { + RISCV_error("UDP interface '%s' not found", + bus_.to_string()); + return; + } + + AttributeType clks; + RISCV_get_clock_services(&clks); + if (clks.size()) { + iclk0_ = static_cast(clks[0u].to_iface()); + } else { + RISCV_error("CPUs not found", NULL); + } + + // Get global settings: + const AttributeType *glb = RISCV_get_global_settings(); + if ((*glb)["SimEnable"].to_bool()) { + if (!run()) { + RISCV_error("Can't create thread.", NULL); + return; + } + } +} + +void Greth::busyLoop() { + int bytes; + uint8_t *tbuf; + uint32_t bytes_to_read; + UdpEdclCommonType req; + RISCV_info("Ethernet thread was started", NULL); + trans_.source_idx = sysBusMasterID_.to_int(); + + while (isEnabled()) { + bytes = + itransport_->readData(rxbuf_, static_cast(sizeof(rxbuf_))); + + if (bytes == 0) { + continue; + } + + req.control.word = read32(&rxbuf_[2]); + req.address = read32(&rxbuf_[6]); + if (seq_cnt_ != req.control.request.seqidx) { + sendNAK(&req); + continue; + } + + trans_.addr = req.address; + if (req.control.request.write == 0) { + trans_.action = MemAction_Read; + trans_.wstrb = 0; + tbuf = &txbuf_[10]; + bytes = sizeof(UdpEdclCommonType) + req.control.request.len; + } else { + trans_.action = MemAction_Write; + tbuf = &rxbuf_[10]; + bytes = sizeof(UdpEdclCommonType); + } + bytes_to_read = req.control.request.len; + while (bytes_to_read) { + trans_.xsize = bytes_to_read; + if (trans_.xsize > 8) { + trans_.xsize = 8; + } + if (trans_.action == MemAction_Write) { + memcpy(trans_.wpayload.b8, tbuf, trans_.xsize); + trans_.wstrb = (1 << trans_.xsize) - 1; + } + RISCV_event_clear(&event_tap_); + ibus_->nb_transport(&trans_, this); + if (RISCV_event_wait_ms(&event_tap_, 500) != 0) { + RISCV_error("CPU queue callback timeout", NULL); + } else if (trans_.action == MemAction_Read) { + memcpy(tbuf, trans_.rpayload.b8, trans_.xsize); + } + tbuf += trans_.xsize; + trans_.addr += trans_.xsize; + bytes_to_read -= trans_.xsize; + } + + req.control.response.nak = 0; + req.control.response.seqidx = seq_cnt_; + write32(&txbuf_[2], req.control.word); + + seq_cnt_++; + itransport_->sendData(txbuf_, bytes); + } +} + +void Greth::nb_response(Axi4TransactionType *trans) { + RISCV_event_set(&event_tap_); +} + +ETransStatus Greth::b_transport(Axi4TransactionType *trans) { + RISCV_error("ETH Slave registers not implemented", NULL); + return TRANS_OK; +} + +void Greth::sendNAK(UdpEdclCommonType *req) { + req->control.response.nak = 1; + req->control.response.seqidx = seq_cnt_; + req->control.response.len = 0; + write32(&txbuf_[2], req->control.word); + write32(&txbuf_[6], req->address); + + itransport_->sendData(txbuf_, sizeof(UdpEdclCommonType)); +} + +uint32_t Greth::read32(uint8_t *buf) { + return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3] << 0); +} + +void Greth::write32(uint8_t *buf, uint32_t v) { + buf[0] = static_cast((v >> 24) & 0xFF); + buf[1] = static_cast((v >> 16) & 0xFF); + buf[2] = static_cast((v >> 8) & 0xFF); + buf[3] = static_cast(v & 0xFF); +} + +} // namespace debugger
src/common/debug/greth.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/common/debug/greth.h =================================================================== --- src/common/debug/greth.h (nonexistent) +++ src/common/debug/greth.h (revision 5) @@ -0,0 +1,109 @@ +/** + * @file + * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Ethernet MAC device functional model. + */ + +#ifndef __DEBUGGER_COMMON_DEBUG_GRETH_H__ +#define __DEBUGGER_COMMON_DEBUG_GRETH_H__ + +#include +#include +#include "coreservices/ithread.h" +#include "coreservices/iclock.h" +#include "coreservices/imemop.h" +#include "coreservices/ilink.h" +#include "coreservices/irawlistener.h" + +namespace debugger { + +struct greth_map { + uint32_t rsrv1; + uint64_t rsrv[2]; +}; + +struct EdclControlRequestType { + // 32 bits fields: + uint32_t unused : 7; + uint32_t len : 10; + uint32_t write : 1; // read = 0; write = 1 + uint32_t seqidx : 14; // sequence id + /* uint32 data; */ // 0 to 242 words +}; + + +struct EdclControlResponseType { + // 32 bits fields: + uint32_t unused : 7; + uint32_t len : 10; + uint32_t nak : 1; // ACK = 0; NAK = 1 + uint32_t seqidx : 14; // sequence id + /* uint32 data; */ // 0 to 242 words +}; + +#pragma pack(1) +struct UdpEdclCommonType { + uint16_t offset; + union ControlType { + uint32_t word; + EdclControlRequestType request; + EdclControlResponseType response; + } control; + uint32_t address; + /* uint32 data; */ // 0 to 242 words +}; +#pragma pack() + +class Greth : public IService, + public IThread, + public IMemoryOperation, + public IAxi4NbResponse { + public: + explicit Greth(const char *name); + virtual ~Greth(); + + /** IService interface */ + virtual void postinitService(); + + /** IMemoryOperation */ + virtual ETransStatus b_transport(Axi4TransactionType *trans); + + /** IAxi4NbResponse */ + virtual void nb_response(Axi4TransactionType *trans); + + protected: + /** IThread interface */ + virtual void busyLoop(); + + private: + void write32(uint8_t *buf, uint32_t v); + uint32_t read32(uint8_t *buf); + void sendNAK(UdpEdclCommonType *req); + + private: + AttributeType ip_; + AttributeType mac_; + AttributeType bus_; + AttributeType transport_; + AttributeType sysBusMasterID_; + + IMemoryOperation *ibus_; + IClock *iclk0_; + ILink *itransport_; + + uint8_t rxbuf_[1<<12]; + uint8_t txbuf_[1<<12]; + uint32_t seq_cnt_ : 14; + + Axi4TransactionType trans_; + event_def event_tap_; + + greth_map regs_; +}; + +DECLARE_CLASS(Greth) + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_DEBUG_GRETH_H__
src/common/debug/greth.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/generic/cpu_generic.cpp =================================================================== --- src/common/generic/cpu_generic.cpp (nonexistent) +++ src/common/generic/cpu_generic.cpp (revision 5) @@ -0,0 +1,508 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "cpu_generic.h" +#include "coreservices/isocinfo.h" + +namespace debugger { + +CpuGeneric::CpuGeneric(const char *name) + : IService(name), IHap(HAP_ConfigDone), + pc_(this, "pc", DSUREG(ureg.v.pc)), + npc_(this, "npc", DSUREG(ureg.v.npc)), + status_(this, "status", DSUREG(udbg.v.control)), + stepping_cnt_(this, "stepping_cnt", DSUREG(udbg.v.stepping_mode_steps)), + clock_cnt_(this, "clock_cnt", DSUREG(udbg.v.clock_cnt)), + executed_cnt_(this, "executed_cnt", DSUREG(udbg.v.executed_cnt)), + stackTraceCnt_(this, "stack_trace_cnt", DSUREG(ureg.v.stack_trace_cnt)), + stackTraceBuf_(this, "stack_trace_buf", DSUREG(ureg.v.stack_trace_buf), 0), + br_control_(this, "br_control", DSUREG(udbg.v.br_ctrl)), + br_fetch_addr_(this, "br_fetch_addr", DSUREG(udbg.v.br_address_fetch)), + br_fetch_instr_(this, "br_fetch_instr", DSUREG(udbg.v.br_instr_fetch)), + br_hw_add_(this, "br_hw_add", DSUREG(udbg.v.add_breakpoint)), + br_hw_remove_(this, "br_hw_remove", DSUREG(udbg.v.remove_breakpoint)) { + registerInterface(static_cast(this)); + registerInterface(static_cast(this)); + registerInterface(static_cast(this)); + registerInterface(static_cast(this)); + registerInterface(static_cast(this)); + registerInterface(static_cast(this)); + registerAttribute("Enable", &isEnable_); + registerAttribute("SysBus", &sysBus_); + registerAttribute("DbgBus", &dbgBus_); + registerAttribute("SysBusWidthBytes", &sysBusWidthBytes_); + registerAttribute("SourceCode", &sourceCode_); + registerAttribute("StackTraceSize", &stackTraceSize_); + registerAttribute("FreqHz", &freqHz_); + registerAttribute("GenerateRegTraceFile", &generateRegTraceFile_); + registerAttribute("GenerateMemTraceFile", &generateMemTraceFile_); + registerAttribute("ResetVector", &resetVector_); + registerAttribute("SysBusMasterID", &sysBusMasterID_); + + char tstr[256]; + RISCV_sprintf(tstr, sizeof(tstr), "eventConfigDone_%s", name); + RISCV_event_create(&eventConfigDone_, tstr); + RISCV_register_hap(static_cast(this)); + + isysbus_ = 0; + estate_ = CORE_OFF; + step_cnt_ = 0; + pc_z_.val = 0; + hw_stepping_break_ = 0; + interrupt_pending_ = 0; + sw_breakpoint_ = false; + hw_breakpoint_ = false; + skip_sw_breakpoint_ = false; + hwBreakpoints_.make_list(0); + + dport_.valid = 0; + reg_trace_file = 0; + mem_trace_file = 0; +} + +CpuGeneric::~CpuGeneric() { + RISCV_event_close(&eventConfigDone_); + if (reg_trace_file) { + reg_trace_file->close(); + delete reg_trace_file; + } + if (mem_trace_file) { + mem_trace_file->close(); + delete mem_trace_file; + } +} + +void CpuGeneric::postinitService() { + isysbus_ = static_cast( + RISCV_get_service_iface(sysBus_.to_string(), IFACE_MEMORY_OPERATION)); + if (!isysbus_) { + RISCV_error("System Bus interface '%s' not found", + sysBus_.to_string()); + return; + } + + idbgbus_ = static_cast( + RISCV_get_service_iface(dbgBus_.to_string(), IFACE_MEMORY_OPERATION)); + if (!idbgbus_) { + RISCV_error("Debug Bus interface '%s' not found", + dbgBus_.to_string()); + return; + } + + isrc_ = static_cast( + RISCV_get_service_iface(sourceCode_.to_string(), IFACE_SOURCE_CODE)); + if (!isrc_) { + RISCV_error("Source code interface '%s' not found", + sourceCode_.to_string()); + return; + } + + stackTraceBuf_.setRegTotal(2 * stackTraceSize_.to_int()); + + // Get global settings: + const AttributeType *glb = RISCV_get_global_settings(); + if ((*glb)["SimEnable"].to_bool() && isEnable_.to_bool()) { + if (!run()) { + RISCV_error("Can't create thread.", NULL); + return; + } + if (generateRegTraceFile_.to_bool()) { + reg_trace_file = new std::ofstream("river_func_regs.log"); + } + if (generateMemTraceFile_.to_bool()) { + mem_trace_file = new std::ofstream("river_func_mem.log"); + } + } +} + +void CpuGeneric::hapTriggered(IFace *isrc, EHapType type, + const char *descr) { + RISCV_event_set(&eventConfigDone_); +} + +void CpuGeneric::busyLoop() { + RISCV_event_wait(&eventConfigDone_); + + while (isEnabled()) { + updatePipeline(); + } +} + +void CpuGeneric::updatePipeline() { + if (dport_.valid) { + dport_.valid = 0; + updateDebugPort(); + } + + if (!updateState()) { + return; + } + + pc_.setValue(npc_.getValue()); + branch_ = false; + oplen_ = 0; + + if (!checkHwBreakpoint()) { + fetchILine(); + instr_ = decodeInstruction(cacheline_); + + trackContextStart(); + if (instr_) { + oplen_ = instr_->exec(cacheline_); + } else { + generateIllegalOpcode(); + } + trackContextEnd(); + + pc_z_ = pc_.getValue(); + } + + if (!branch_) { + npc_.setValue(pc_.getValue().val + oplen_); + } + + updateQueue(); + + handleTrap(); +} + +bool CpuGeneric::updateState() { + bool upd = true; + switch (estate_) { + case CORE_OFF: + case CORE_Halted: + updateQueue(); + upd = false; + break; + case CORE_Stepping: + if (hw_stepping_break_ <= step_cnt_) { + halt("Stepping breakpoint"); + upd = false; + } + break; + default:; + } + if (upd) { + step_cnt_++; + } + return upd; +} + +void CpuGeneric::updateQueue() { + IFace *cb; + queue_.initProc(); + queue_.pushPreQueued(); + + while ((cb = queue_.getNext(step_cnt_)) != 0) { + static_cast(cb)->stepCallback(step_cnt_); + } +} + +void CpuGeneric::fetchILine() { + trans_.action = MemAction_Read; + trans_.addr = pc_.getValue().val; + trans_.xsize = 4; + trans_.wstrb = 0; + dma_memop(&trans_); + cacheline_[0].val = trans_.rpayload.b64[0]; + if (skip_sw_breakpoint_ && trans_.addr == br_fetch_addr_.getValue().val) { + skip_sw_breakpoint_ = false; + cacheline_[0].buf32[0] = br_fetch_instr_.getValue().buf32[0]; + } +} + +void CpuGeneric::registerStepCallback(IClockListener *cb, + uint64_t t) { + if (!isEnabled() && t <= step_cnt_) { + cb->stepCallback(t); + return; + } + queue_.put(t, cb); +} + +void CpuGeneric::setBranch(uint64_t npc) { + branch_ = true; + npc_.setValue(npc); +} + +void CpuGeneric::pushStackTrace() { + int cnt = static_cast(stackTraceCnt_.getValue().val); + if (cnt >= stackTraceSize_.to_int()) { + return; + } + stackTraceBuf_.write(2*cnt, pc_.getValue().val); + stackTraceBuf_.write(2*cnt + 1, npc_.getValue().val); + stackTraceCnt_.setValue(cnt + 1); +} + +void CpuGeneric::popStackTrace() { + uint64_t cnt = stackTraceCnt_.getValue().val; + if (cnt) { + stackTraceCnt_.setValue(cnt - 1); + } +} + +void CpuGeneric::dma_memop(Axi4TransactionType *tr) { + tr->source_idx = sysBusMasterID_.to_int(); + if (tr->xsize <= sysBusWidthBytes_.to_uint32()) { + isysbus_->b_transport(tr); + } else { + // 1-byte access for HC08 + Axi4TransactionType tr1 = *tr; + tr1.xsize = 1; + tr1.wstrb = 1; + for (unsigned i = 0; i < tr->xsize; i++) { + tr1.addr = tr->addr + i; + if (tr->action == MemAction_Write) { + tr1.wpayload.b8[0] = tr->wpayload.b8[i]; + } + isysbus_->b_transport(&tr1); + if (tr->action == MemAction_Read) { + tr->rpayload.b8[i] = tr1.rpayload.b8[0]; + } + } + } + if (!mem_trace_file) { + //if (!reg_trace_file) { + return; + } + + char tstr[512]; + Reg64Type pload = {0}; + if (tr->action == MemAction_Read) { + if (tr->xsize == 4) { + pload.buf32[0] = tr->rpayload.b32[0]; + } else { + pload.val = tr->rpayload.b64[0]; + } + RISCV_sprintf(tstr, sizeof(tstr), + "%08x: [%08x] => %016" RV_PRI64 "x\n", + pc_.getValue().buf32[0], + static_cast(tr->addr), + pload.val); + } else { + if (tr->xsize == 4) { + pload.buf32[0] = tr->wpayload.b32[0]; + } else { + pload.val = tr->wpayload.b64[0]; + } + RISCV_sprintf(tstr, sizeof(tstr), + "%08x: [%08x] <= %016" RV_PRI64 "x\n", + pc_.getValue().buf32[0], + static_cast(tr->addr), + pload.val); + } + (*mem_trace_file) << tstr; + mem_trace_file->flush(); +} + +void CpuGeneric::go() { + if (estate_ == CORE_OFF) { + RISCV_error("CPU is turned-off", 0); + return; + } + estate_ = CORE_Normal; +} + +void CpuGeneric::step() { + if (estate_ == CORE_OFF) { + RISCV_error("CPU is turned-off", 0); + return; + } + hw_stepping_break_ = step_cnt_ + stepping_cnt_.getValue().val; + estate_ = CORE_Stepping; +} + +void CpuGeneric::halt(const char *descr) { + if (estate_ == CORE_OFF) { + RISCV_error("CPU is turned-off", 0); + return; + } + char strop[32]; + uint8_t tbyte; + unsigned bytetot = oplen_; + if (!bytetot) { + bytetot = 1; + } + for (unsigned i = 0; i < bytetot; i++) { + if (endianess() == LittleEndian) { + tbyte = cacheline_[0].buf[bytetot-i-1]; + } else { + tbyte = cacheline_[0].buf[i]; + } + RISCV_sprintf(&strop[2*i], sizeof(strop)-2*i, "%02x", tbyte); + } + + if (descr == NULL) { + RISCV_info("[%6" RV_PRI64 "d] pc:%04" RV_PRI64 "x: %s \t CPU halted", + step_cnt_, pc_.getValue().val, strop); + } else { + RISCV_info("[%6" RV_PRI64 "d] pc:%04" RV_PRI64 "x: %s\t %s", + step_cnt_, pc_.getValue().val, strop, descr); + } + estate_ = CORE_Halted; + RISCV_trigger_hap(getInterface(IFACE_SERVICE), HAP_Halt, "Descr"); +} + +void CpuGeneric::reset(bool active) { + interrupt_pending_ = 0; + status_.reset(active); + stackTraceCnt_.reset(active); + pc_.setValue(getResetAddress()); + npc_.setValue(getResetAddress()); + if (!active && estate_ == CORE_OFF) { + // Turn ON: + estate_ = CORE_Halted;//CORE_Normal; + RISCV_trigger_hap(static_cast(this), + HAP_CpuTurnON, "CPU Turned ON"); + } else if (active) { + // Turn OFF: + estate_ = CORE_OFF; + RISCV_trigger_hap(static_cast(this), + HAP_CpuTurnOFF, "CPU Turned OFF"); + } + hw_breakpoint_ = false; + sw_breakpoint_ = false; +} + +void CpuGeneric::updateDebugPort() { + DebugPortTransactionType *trans = dport_.trans; + Axi4TransactionType tr; + tr.xsize = 8; + tr.source_idx = 0; + if (trans->write) { + tr.action = MemAction_Write; + tr.wpayload.b64[0] = trans->wdata; + tr.wstrb = 0xFF; + } else { + tr.action = MemAction_Read; + tr.rpayload.b64[0] = 0; + } + tr.addr = (static_cast(trans->region) << 15) | trans->addr; + idbgbus_->b_transport(&tr); + + trans->rdata = tr.rpayload.b64[0];; + dport_.cb->nb_response_debug_port(trans); +} + +void CpuGeneric::nb_transport_debug_port(DebugPortTransactionType *trans, + IDbgNbResponse *cb) { + dport_.trans = trans; + dport_.cb = cb; + dport_.valid = true; +} + +void CpuGeneric::addHwBreakpoint(uint64_t addr) { + AttributeType item; + item.make_uint64(addr); + hwBreakpoints_.add_to_list(&item); + hwBreakpoints_.sort(); + for (unsigned i = 0; i < hwBreakpoints_.size(); i++) { + RISCV_debug("Breakpoint[%d]: 0x%04" RV_PRI64 "x", + i, hwBreakpoints_[i].to_uint64()); + } +} + +void CpuGeneric::removeHwBreakpoint(uint64_t addr) { + for (unsigned i = 0; i < hwBreakpoints_.size(); i++) { + if (addr == hwBreakpoints_[i].to_uint64()) { + hwBreakpoints_.remove_from_list(i); + hwBreakpoints_.sort(); + return; + } + } +} + +bool CpuGeneric::checkHwBreakpoint() { + uint64_t pc = pc_.getValue().val; + if (hw_breakpoint_ && pc == hw_break_addr_) { + hw_breakpoint_ = false; + return false; + } + hw_breakpoint_ = false; + + for (unsigned i = 0; i < hwBreakpoints_.size(); i++) { + uint64_t bradr = hwBreakpoints_[i].to_uint64(); + if (pc < bradr) { + // Sorted list + break; + } + if (pc == bradr) { + hw_break_addr_ = pc; + hw_breakpoint_ = true; + halt("Hw breakpoint"); + return true; + } + } + return false; +} + +void CpuGeneric::skipBreakpoint() { + skip_sw_breakpoint_ = true; + sw_breakpoint_ = false; +} + + +uint64_t GenericStatusType::aboutToRead(uint64_t cur_val) { + GenericCpuControlType ctrl; + CpuGeneric *pcpu = static_cast(parent_); + ctrl.val = 0; + ctrl.bits.halt = pcpu->isHalt() || !pcpu->isOn() ? 1 : 0; + ctrl.bits.sw_breakpoint = pcpu->isSwBreakpoint() ? 1 : 0; + ctrl.bits.hw_breakpoint = pcpu->isHwBreakpoint() ? 1 : 0; + return ctrl.val; +} + +uint64_t GenericStatusType::aboutToWrite(uint64_t new_val) { + GenericCpuControlType ctrl; + CpuGeneric *pcpu = static_cast(parent_); + ctrl.val = new_val; + if (ctrl.bits.halt) { + pcpu->halt("halted from DSU"); + } else if (ctrl.bits.stepping) { + pcpu->step(); + } else { + pcpu->go(); + } + return new_val; +} + +uint64_t FetchedBreakpointType::aboutToWrite(uint64_t new_val) { + CpuGeneric *pcpu = static_cast(parent_); + pcpu->skipBreakpoint(); + return new_val; +} + +uint64_t AddBreakpointType::aboutToWrite(uint64_t new_val) { + CpuGeneric *pcpu = static_cast(parent_); + pcpu->addHwBreakpoint(new_val); + return new_val; +} + +uint64_t RemoveBreakpointType::aboutToWrite(uint64_t new_val) { + CpuGeneric *pcpu = static_cast(parent_); + pcpu->removeHwBreakpoint(new_val); + return new_val; +} + +uint64_t StepCounterType::aboutToRead(uint64_t cur_val) { + CpuGeneric *pcpu = static_cast(parent_); + return pcpu->getStepCounter(); +} + +} // namespace debugger +
src/common/generic/cpu_generic.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/common/generic/cpu_generic.h =================================================================== --- src/common/generic/cpu_generic.h (nonexistent) +++ src/common/generic/cpu_generic.h (revision 5) @@ -0,0 +1,226 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEBUGGER_COMMON_CPU_GENERIC_H__ +#define __DEBUGGER_COMMON_CPU_GENERIC_H__ + +#include +#include +#include +#include +#include "coreservices/ithread.h" +#include "coreservices/icpugen.h" +#include "coreservices/icpufunctional.h" +#include "coreservices/imemop.h" +#include "coreservices/iclock.h" +#include "coreservices/iclklistener.h" +#include "coreservices/ireset.h" +#include "coreservices/isrccode.h" +#include "generic/mapreg.h" +#include "debug/debugmap.h" +#include + +namespace debugger { + +class GenericStatusType : public MappedReg64Type { + public: + GenericStatusType(IService *parent, const char *name, uint64_t addr) : + MappedReg64Type(parent, name, addr) { + } + protected: + virtual uint64_t aboutToRead(uint64_t cur_val); + virtual uint64_t aboutToWrite(uint64_t new_val); +}; + +class FetchedBreakpointType : public MappedReg64Type { + public: + FetchedBreakpointType(IService *parent, const char *name, uint64_t addr) + : MappedReg64Type(parent, name, addr) { + } + protected: + virtual uint64_t aboutToWrite(uint64_t new_val); +}; + +class AddBreakpointType : public MappedReg64Type { + public: + AddBreakpointType(IService *parent, const char *name, uint64_t addr) + : MappedReg64Type(parent, name, addr) { + } + protected: + virtual uint64_t aboutToWrite(uint64_t new_val); +}; + +class RemoveBreakpointType : public MappedReg64Type { + public: + RemoveBreakpointType(IService *parent, const char *name, uint64_t addr) + : MappedReg64Type(parent, name, addr) { + } + protected: + virtual uint64_t aboutToWrite(uint64_t new_val); +}; + +class StepCounterType : public MappedReg64Type { + public: + StepCounterType(IService *parent, const char *name, uint64_t addr) + : MappedReg64Type(parent, name, addr) { + } + protected: + virtual uint64_t aboutToRead(uint64_t cur_val); +}; + +class CpuGeneric : public IService, + public IThread, + public ICpuGeneric, + public ICpuFunctional, + public IClock, + public IResetListener, + public IHap { + public: + explicit CpuGeneric(const char *name); + ~CpuGeneric(); + + /** IService interface */ + virtual void postinitService(); + + /** ICpuGeneric interface */ + virtual void raiseSignal(int idx) = 0; + virtual void lowerSignal(int idx) = 0; + virtual void nb_transport_debug_port(DebugPortTransactionType *trans, + IDbgNbResponse *cb); + + /** ICpuFunctional */ + virtual uint64_t getPC() { return pc_.getValue().val; } + virtual void setBranch(uint64_t npc); + virtual void pushStackTrace(); + virtual void popStackTrace(); + virtual uint64_t getPrvLevel() { return cur_prv_level; } + virtual void setPrvLevel(uint64_t lvl) { cur_prv_level = lvl; } + virtual void dma_memop(Axi4TransactionType *tr); + virtual bool isOn() { return estate_ != CORE_OFF; } + virtual bool isHalt() { return estate_ == CORE_Halted; } + virtual bool isSwBreakpoint() { return sw_breakpoint_; } + virtual bool isHwBreakpoint() { return hw_breakpoint_; } + virtual void go(); + virtual void halt(const char *descr); + virtual void step(); + virtual void addHwBreakpoint(uint64_t addr); + virtual void removeHwBreakpoint(uint64_t addr); + virtual void skipBreakpoint(); + protected: + virtual uint64_t getResetAddress() { return resetVector_.to_uint64(); } + virtual EEndianessType endianess() = 0; + virtual GenericInstruction *decodeInstruction(Reg64Type *cache) = 0; + virtual void generateIllegalOpcode() = 0; + virtual void handleTrap() = 0; + virtual void trackContextStart() {} + virtual void trackContextEnd() {} + + public: + /** IClock */ + virtual uint64_t getStepCounter() { return step_cnt_; } + virtual void registerStepCallback(IClockListener *cb, uint64_t t); + virtual double getFreqHz() { + return static_cast(freqHz_.to_int64()); + } + + /** IResetListener interface */ + virtual void reset(bool active); + + /** IHap */ + virtual void hapTriggered(IFace *isrc, EHapType type, const char *descr); + + protected: + /** IThread interface */ + virtual void busyLoop(); + + void updatePipeline(); + bool updateState(); + void fetchILine(); + void updateDebugPort(); + void updateQueue(); + bool checkHwBreakpoint(); + + protected: + AttributeType isEnable_; + AttributeType freqHz_; + AttributeType sysBus_; + AttributeType dbgBus_; + AttributeType sysBusWidthBytes_; + AttributeType sourceCode_; + AttributeType stackTraceSize_; + AttributeType generateRegTraceFile_; + AttributeType generateMemTraceFile_; + AttributeType resetVector_; + AttributeType sysBusMasterID_; + AttributeType hwBreakpoints_; + + ISourceCode *isrc_; + IMemoryOperation *isysbus_; + IMemoryOperation *idbgbus_; + GenericInstruction *instr_; + + uint64_t step_cnt_; + uint64_t hw_stepping_break_; + bool branch_; + unsigned oplen_; + MappedReg64Type pc_; + MappedReg64Type npc_; + GenericStatusType status_; + MappedReg64Type stepping_cnt_; + StepCounterType clock_cnt_; + StepCounterType executed_cnt_; + MappedReg64Type stackTraceCnt_; // Hardware stack trace buffer + GenericReg64Bank stackTraceBuf_; // [[from,to],*] + MappedReg64Type br_control_; // Enable/disable Trap on break + MappedReg64Type br_fetch_addr_; // Skip breakpoint at address + FetchedBreakpointType br_fetch_instr_; // Use this instruction on address + AddBreakpointType br_hw_add_; + RemoveBreakpointType br_hw_remove_; + + Reg64Type pc_z_; + uint64_t interrupt_pending_; + bool sw_breakpoint_; + bool skip_sw_breakpoint_; + bool hw_breakpoint_; + uint64_t hw_break_addr_; // Last hit breakpoint to skip it on next step + + event_def eventConfigDone_; + ClockAsyncTQueueType queue_; + + enum ECoreState { + CORE_OFF, + CORE_Halted, + CORE_Normal, + CORE_Stepping + } estate_; + + Axi4TransactionType trans_; + Reg64Type cacheline_[512/4]; + struct DebugPortType { + bool valid; + DebugPortTransactionType *trans; + IDbgNbResponse *cb; + } dport_; + + uint64_t cur_prv_level; + + std::ofstream *reg_trace_file; + std::ofstream *mem_trace_file; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_CPU_GENERIC_H__
src/common/generic/cpu_generic.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/generic/iotypes.cpp =================================================================== --- src/common/generic/iotypes.cpp (nonexistent) +++ src/common/generic/iotypes.cpp (revision 5) @@ -0,0 +1,233 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "iotypes.h" + +namespace debugger { + +IOReg8Type::IOReg8Type(IService *parent, const char *name, + uint16_t addr, uint16_t len, int priority) { + if (parent == NULL) { + } else { + parent->registerPortInterface(name, + static_cast(this)); + parent->registerPortInterface(name, static_cast(this)); + parent->registerPortInterface(name, + static_cast(this)); + } + parent_ = parent; + portListeners_.make_list(0); + regname_.make_string(name); + baseAddress_.make_uint64(addr); + length_.make_uint64(len); + priority_.make_int64(priority); + value.byte = 0; + hard_reset_value_ = 0; +} + +IFace *IOReg8Type::getInterface(const char *name) { + if (strcmp(name, IFACE_MEMORY_OPERATION) == 0) { + return static_cast(this); + } + return parent_->getInterface(name); +} + +void IOReg8Type::reset(bool active) { + if (!active) { + return; + } + write(hard_reset_value_); +} + +ETransStatus IOReg8Type::b_transport(Axi4TransactionType *trans) { + uint16_t addr = static_cast(trans->addr); + if (trans->action == MemAction_Read) { + trans->rpayload.b8[0] = read(); + RISCV_debug("Read %s [%02x] => %02x", + regName(), addr, trans->rpayload.b8[0]); + } else { + write(trans->wpayload.b8[0]); + RISCV_debug("Write %s [%02x] <= %02x", + regName(), addr, trans->wpayload.b8[0]); + } + return TRANS_OK; +} + +uint8_t IOReg8Type::read() { + IIOPortListener *lstn; + uint8_t odata = value.byte; + for (unsigned i = 0; i < portListeners_.size(); i++) { + lstn = static_cast(portListeners_[i].to_iface()); + lstn->readData(&odata, get_direction()); + } + return odata; +} + +void IOReg8Type::write(uint8_t data) { + IIOPortListener *lstn; + value.byte = data; + for (unsigned i = 0; i < portListeners_.size(); i++) { + lstn = static_cast(portListeners_[i].to_iface()); + lstn->writeData(data, get_direction()); + } + for (unsigned i = 0; i < portListeners_.size(); i++) { + lstn = static_cast(portListeners_[i].to_iface()); + lstn->latch(); + } +} + +void IOReg8Type::registerPortListener(IFace *listener) { + AttributeType item; + item.make_iface(listener); + portListeners_.add_to_list(&item); +} + +void IOReg8Type::unregisterPortListener(IFace *listener) { + for (unsigned i = 0; i < portListeners_.size(); i++) { + if (listener == portListeners_[i].to_iface()) { + portListeners_.remove_from_list(i); + break; + } + } +} + +/** */ +IOPinType::IOPinType(IService *parent, const char *name) : parent_(parent) { + pinName_.make_string(name); + iwire_ = 0; + value_ = 0; + bitIdx_ = 0; + access_ = 0; + + char tstr[256]; + RISCV_sprintf(tstr, sizeof(tstr), "pin_%s", name); + parent_->registerAttribute(tstr, &IOPinTypeCfg_); +} + +// Memory access use direction xDD register value (IN/OUT) +void IOPinType::readData(uint8_t *val, uint8_t mask) { + uint8_t v; + if (iwire_ && (access_ & READ_MASK)) { + v = iwire_->getLevel(); + } else { + v = aboutToRead(value_); + } + *val &= ~(1 << bitIdx_); + *val |= (v << bitIdx_); +} + +void IOPinType::writeData(uint8_t val, uint8_t mask) { + prelatch_ = (val >> bitIdx_) & 0x1; + if (iwire_ && (access_ & WRITE_MASK) && (mask & (1u << bitIdx_))) { + iwire_->setLevel(prelatch_ == 0 ? false : true); + } else { + aboutToWrite(value_, prelatch_); + } +} + +// Direct access to wire doesn't use Direction xDD mask register +uint8_t IOPinType::get_bit() { + if (iwire_ && (access_ & READ_MASK)) { + return iwire_->getLevel() ? 1u : 0; + } + return value_; +} + +void IOPinType::set_bit(uint8_t v) { + if (iwire_ && (access_ & WRITE_MASK)) { + iwire_->setLevel(v == 0 ? false : true); + } + prelatch_ = v; + value_ = prelatch_; +} + + +void IOPinType::latch() { + value_ = prelatch_; +} + +void IOPinType::postinit() { + connectToBit(IOPinTypeCfg_); + if (IOPinTypeCfg_.size() >= 3) { + connectToWire(IOPinTypeCfg_[2]); + } +} + +void IOPinType::connectToBit(const AttributeType &cfg) { + if (!cfg.is_list() || cfg.size() < 2) { + RISCV_printf(NULL, LOG_ERROR, + "Cannot connect IOPinType %s: Wrong format of port attribute", + pinName_.to_string()); + return; + } + IIOPort *iport = 0; + if (cfg[0u].is_string()) { + iport = static_cast(RISCV_get_service_iface( + cfg[0u].to_string(), IFACE_IOPORT)); + } else if (cfg[0u].is_list()) { + const AttributeType &prt = cfg[0u]; + iport = static_cast(RISCV_get_service_port_iface( + prt[0u].to_string(), prt[1].to_string(), IFACE_IOPORT)); + } + bitIdx_ = cfg[1].to_int(); + + if (iport == 0) { + RISCV_printf(NULL, LOG_ERROR, + "Cannot connect IOPinType: Can't get port interface %s", + cfg[0u].to_string()); + return; + } + iport->registerPortListener(static_cast(this)); +} + +void IOPinType::connectToWire(const AttributeType &cfg) { + if (!cfg.is_list() || cfg.size() < 2) { + RISCV_printf(NULL, LOG_ERROR, + "[%s] Cannot connect IWire input: wrong attribute", + pinName_.to_string()); + return; + } + const char *rw; + if (cfg.size() == 2) { + iwire_ = static_cast(RISCV_get_service_iface( + cfg[0u].to_string(), IFACE_WIRE)); + rw = cfg[1].to_string(); + } else { + iwire_ = static_cast(RISCV_get_service_port_iface( + cfg[0u].to_string(), cfg[1].to_string(), IFACE_WIRE)); + rw = cfg[2].to_string(); + } + if (!iwire_) { + RISCV_printf(NULL, LOG_ERROR, + "[%s] Cannot find IWire interface in %s", + pinName_.to_string(), cfg[0u].to_string()); + return; + } + + access_ = 0; + if (strstr(rw, "r")) { + access_ |= READ_MASK; + prelatch_ = iwire_->getLevel(); + value_ = prelatch_; + } + if (strstr(rw, "w")) { + access_ |= WRITE_MASK; + } +} + +} // namespace debugger +
src/common/generic/iotypes.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/common/generic/iotypes.h =================================================================== --- src/common/generic/iotypes.h (nonexistent) +++ src/common/generic/iotypes.h (revision 5) @@ -0,0 +1,115 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEBUGGER_COMMON_GENERIC_IOTYPES_H__ +#define __DEBUGGER_COMMON_GENERIC_IOTYPES_H__ + +#include +#include +#include "coreservices/iioport.h" +#include "coreservices/ireset.h" +#include "coreservices/iwire.h" + +namespace debugger { + +class IOReg8Type : public IMemoryOperation, + public IIOPort, + public IResetListener { + public: + IOReg8Type(IService *parent, const char *name, + uint16_t addr, uint16_t len, int priority = 1); + + /** IMemoryOperation methods */ + virtual ETransStatus b_transport(Axi4TransactionType *trans); + + /** IIOPort */ + virtual void registerPortListener(IFace *listener); + virtual void unregisterPortListener(IFace *listener); + + /** IResetListener interface */ + virtual void reset(bool active); + + /** General access methods: */ + const char *regName() { return regname_.to_string(); } + uint8_t getValue() { return value.byte; } + void setValue(uint8_t v) { value.byte = v; } + + protected: + virtual uint8_t read(); + virtual void write(uint8_t val); + virtual uint8_t get_direction() {return 0u; } + + protected: + // Debug output compatibility + IFace *getInterface(const char *name); + + protected: + IService *parent_; + AttributeType regname_; + AttributeType portListeners_; + Reg8Type value; + uint8_t hard_reset_value_; +}; + + +class IOPinType : public IIOPortListener { + public: + IOPinType(IService *parent, const char *name); + + /** IIOPortListener */ + virtual void readData(uint8_t *val, uint8_t mask); + virtual void writeData(uint8_t val, uint8_t mask); + virtual void latch(); + + /** generic accessors */ + void postinit(); + void connectToBit(const AttributeType &cfg); + void connectToWire(const AttributeType &cfg); + uint8_t get_bit(); + void set_bit(uint8_t v); + + protected: + virtual uint8_t aboutToRead(uint8_t val) { return val; } + virtual void aboutToWrite(uint8_t prev, uint8_t val) {} + + protected: + static const int READ_MASK = 0x1; + static const int WRITE_MASK = 0x2; + + AttributeType pinName_; + AttributeType IOPinTypeCfg_; + IService *parent_; + IWire *iwire_; + uint8_t value_; // triggered + uint8_t prelatch_; // not triggered value + int bitIdx_; + int access_; +}; + +class IOPinTypeDebug : public IOPinType { + public: + IOPinTypeDebug(IService *parent, const char *name) + : IOPinType(parent, name) {} + protected: + // Debug output compatibility + IFace *getInterface(const char *name) { + return parent_->getInterface(name); + } +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_GENERIC_IOTYPES_H__
src/common/generic/iotypes.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/common/generic/mapreg.cpp =================================================================== --- src/common/generic/mapreg.cpp (nonexistent) +++ src/common/generic/mapreg.cpp (revision 5) @@ -0,0 +1,101 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "mapreg.h" + +namespace debugger { + +MappedReg64Type::MappedReg64Type(IService *parent, const char *name, + uint64_t addr, int len, int priority) { + if (parent == NULL) { + } else { + parent->registerPortInterface(name, + static_cast(this)); + parent->registerPortInterface(name, + static_cast(this)); + } + parent_ = parent; + portListeners_.make_list(0); + regname_.make_string(name); + baseAddress_.make_uint64(addr); + length_.make_uint64(len); + priority_.make_int64(priority); + value_.val = 0; + hard_reset_value_ = 0; +} + +IFace *MappedReg64Type::getInterface(const char *name) { + if (strcmp(name, IFACE_MEMORY_OPERATION) == 0) { + return static_cast(this); + } + return parent_->getInterface(name); +} + +void MappedReg64Type::reset(bool active) { + if (!active) { + return; + } + value_.val = hard_reset_value_; +} + +ETransStatus MappedReg64Type::b_transport(Axi4TransactionType *trans) { + uint64_t off = trans->addr - getBaseAddress(); + if (trans->action == MemAction_Read) { + Reg64Type cur; + cur.val = aboutToRead(value_.val); + memcpy(trans->rpayload.b8, &cur.buf[off], trans->xsize); + RISCV_debug("Read %s [%02" RV_PRI64 "x] => %016" RV_PRI64 "x", + regName(), trans->addr, trans->rpayload.b64[0]); + } else { + Reg64Type new_val = value_; + memcpy(&new_val.buf[off], trans->wpayload.b8, trans->xsize); + new_val.val = aboutToWrite(new_val.val); + value_ = new_val; + RISCV_debug("Write %s [%02" RV_PRI64 "x] <= %016" RV_PRI64 "x", + regName(), trans->addr, trans->wpayload.b64[0]); + } + return TRANS_OK; +} + +ETransStatus GenericReg64Bank::b_transport(Axi4TransactionType *trans) { + int idx = static_cast((trans->addr - getBaseAddress()) >> 3); + if (trans->action == MemAction_Read) { + trans->rpayload.b64[0] = read(idx).val; + } else { + write(idx, trans->wpayload.b64[0]); + } + return TRANS_OK; +} + +void GenericReg64Bank::reset() { + memset(regs_, 0, length_.to_int()); +} + +void GenericReg64Bank::setRegTotal(int len) { + if (len * static_cast(sizeof(Reg64Type)) == length_.to_int()) { + return; + } + if (regs_) { + delete [] regs_; + } + length_.make_int64(len * sizeof(Reg64Type)); + regs_ = new Reg64Type[len]; + reset(); +} + +} // namespace debugger +
src/common/generic/mapreg.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/common/generic/mapreg.h =================================================================== --- src/common/generic/mapreg.h (nonexistent) +++ src/common/generic/mapreg.h (revision 5) @@ -0,0 +1,104 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEBUGGER_COMMON_GENERIC_MAPREG_H__ +#define __DEBUGGER_COMMON_GENERIC_MAPREG_H__ + +#include +#include +#include "coreservices/imemop.h" +#include "coreservices/ireset.h" + +namespace debugger { + +class MappedReg64Type : public IMemoryOperation, + public IResetListener { + public: + MappedReg64Type(IService *parent, const char *name, + uint64_t addr, int len = 8, int priority = 1); + + /** IMemoryOperation methods */ + virtual ETransStatus b_transport(Axi4TransactionType *trans); + + /** IResetListener interface */ + virtual void reset(bool active); + + /** General access methods: */ + const char *regName() { return regname_.to_string(); } + Reg64Type getValue() { return value_; } + void setValue(Reg64Type v) { value_ = v; } + void setValue(uint64_t v) { value_.val = v; } + + protected: + /** Possible side effects handlers: */ + virtual uint64_t aboutToRead(uint64_t cur_val) { + return cur_val; + } + virtual uint64_t aboutToWrite(uint64_t new_val) { + return new_val; + } + protected: + // Debug output compatibility + IFace *getInterface(const char *name); + + protected: + IService *parent_; + AttributeType regname_; + AttributeType portListeners_; + Reg64Type value_; + uint64_t hard_reset_value_; +}; + + +class GenericReg64Bank : public IMemoryOperation { + public: + GenericReg64Bank(IService *parent, const char *name, + uint64_t addr, int len) { + parent->registerPortInterface(name, + static_cast(this)); + regs_ = 0; + bankName_.make_string(name); + baseAddress_.make_uint64(addr); + setRegTotal(len); + } + virtual ~GenericReg64Bank() { + if (regs_) { + delete [] regs_; + } + } + + /** IMemoryOperation methods */ + virtual ETransStatus b_transport(Axi4TransactionType *trans); + + /** IResetListener interface */ + virtual void reset(); + + /** General access methods: */ + void setRegTotal(int len); + Reg64Type read(int idx) { return regs_[idx]; } + void write(int idx, Reg64Type val) { regs_[idx] = val; } + void write(int idx, uint64_t val) { regs_[idx].val = val; } + Reg64Type *getp() { return regs_; } + uint64_t *getpR64() { return ®s_[0].val; } + + protected: + AttributeType bankName_; + Reg64Type *regs_; +}; + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_GENERIC_MAPREG_H__
src/common/generic/mapreg.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/cpu_arm_plugin/arm-isa.h =================================================================== --- src/cpu_arm_plugin/arm-isa.h (nonexistent) +++ src/cpu_arm_plugin/arm-isa.h (revision 5) @@ -0,0 +1,363 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEBUGGER_COMMON_ARM_ISA_H__ +#define __DEBUGGER_COMMON_ARM_ISA_H__ + +#include + +namespace debugger { + +static const uint64_t EXT_SIGN_5 = 0xFFFFFFFFFFFFFFF0LL; +static const uint64_t EXT_SIGN_6 = 0xFFFFFFFFFFFFFFE0LL; +static const uint64_t EXT_SIGN_8 = 0xFFFFFFFFFFFFFF80LL; +static const uint64_t EXT_SIGN_9 = 0xFFFFFFFFFFFFFF00LL; +static const uint64_t EXT_SIGN_11 = 0xFFFFFFFFFFFFF800LL; +static const uint64_t EXT_SIGN_12 = 0xFFFFFFFFFFFFF000LL; +static const uint64_t EXT_SIGN_16 = 0xFFFFFFFFFFFF0000LL; +static const uint64_t EXT_SIGN_32 = 0xFFFFFFFF00000000LL; + +/** opcodes: + 0000 = AND - Rd:= Op1 AND Op2 + 0001 = EOR - Rd:= Op1 EOR Op2 + 0010 = SUB - Rd:= Op1 - Op2 + 0011 = RSB - Rd:= Op2 - Op1 + 0100 = ADD - Rd:= Op1 + Op2 + 0101 = ADC - Rd:= Op1 + Op2 + C + 0110 = SBC - Rd:= Op1 - Op2 + C + 0111 = RSC - Rd:= Op2 - Op1 + C + 1000 = TST - set condition codes on Op1 AND Op2 + 1001 = TEQ - set condition codes on Op1 EOR Op2 + 1010 = CMP - set condition codes on Op1 - Op2 + 1011 = CMN - set condition codes on Op1 + Op2 + 1100 = ORR - Rd:= Op1 OR Op2 + 1101 = MOV - Rd:= Op2 + 1110 = BIC - Rd:= Op1 AND NOT Op2 + 1111 = MVN - Rd:= NOT Op2 +*/ +union DataProcessingType { + struct reg_bits_type { + uint32_t rm : 4; // [3:0] 2-nd operand register + uint32_t sh_sel : 1; // [4] 0=shift amount in [11:7], 1=Rs in [11:8] + uint32_t sh_type : 2; // [6:5] 0=logic left; 1=logic right; + // 2=arith right; 3=rotate right + uint32_t shift : 5; // [11:7] shift applied to Rm + uint32_t rd : 4; // [15:12] + uint32_t rn : 4; // [19:16] 1-st operand register + uint32_t S : 1; // [20]. 0=do not alter condition code + uint32_t opcode : 4; // [24:21] + uint32_t I : 1; // [25] = 0 for register instruction + uint32_t zero : 2; // [27:26] = 00b + uint32_t cond : 4; // [31:28] + } reg_bits; + struct imm_bits_type { + uint32_t imm : 8; // [7:0] + uint32_t rotate : 4; // [11:8] rotate applied to imm + uint32_t rd : 4; // [15:12] + uint32_t rn : 4; // [19:16] + uint32_t S : 1; // [20]. 0=do not alter condition code + uint32_t opcode : 4; // [24:21] + uint32_t I : 1; // [25] = 1 for immediate instruction + uint32_t zero : 2; // [27:26] = 00b + uint32_t cond : 4; // [31:28] + } imm_bits; + struct mrs_bits_type { + uint32_t zero12 : 12; // [11:0] = 0 + uint32_t rd : 4; // [15:12] destination + uint32_t mask : 4; // [21:16] + uint32_t b21_20 : 2; // [21:20] 00b=MRS; 10=MSR + uint32_t ps : 1; // [22] 0=CPSR; 1=SPSR_ + uint32_t b27_23 : 5; // [27:23] contant 00010b + uint32_t cond : 4; // [31:28] + } mrs_bits; + struct mov_bits_type { + uint32_t imm12 : 12; + uint32_t rd : 4; + uint32_t imm4 : 4; + uint32_t b27_20 : 8; + uint32_t cond : 4; + } mov_bits; + uint32_t value; +}; + +union SingleDataTransferType { + struct reg_bits_type { + uint32_t rm : 4; // [3:0] offset register + uint32_t sh_sel : 8; // [11:4] shift applied to Rm + uint32_t rd : 4; // [15:12] + uint32_t rn : 4; // [19:16] + uint32_t L : 1; // [20] = 1 load; 0 store + uint32_t W : 1; // [21] = 1 wr addr into base; 0 no write-back + uint32_t B : 1; // [22] = 1 byte; 0 word + uint32_t U : 1; // [23] = 1 add offset; 0 subtruct offset + uint32_t P : 1; // [24] = 1 pre; 0 post + uint32_t I : 1; // [25] = 1 for immediate instruction + uint32_t zeroone : 2; // [27:26] = 01b + uint32_t cond : 4; // [31:28] + } reg_bits; + struct imm_bits_type { + uint32_t imm : 12; // [11:0] + uint32_t rd : 4; // [15:12] + uint32_t rn : 4; // [19:16] + uint32_t L : 1; // [20] = 1 load; 0 store + uint32_t W : 1; // [21] = 1 wr addr into base; 0 no write-back + uint32_t B : 1; // [22] = 1 byte; 0 word + uint32_t U : 1; // [23] = 1 add offset; 0 subtruct offset + uint32_t P : 1; // [24] = 1 pre / 0 post + uint32_t I : 1; // [25] = 1 for immediate instruction + uint32_t zeroone : 2; // [27:26] = 01b + uint32_t cond : 4; // [31:28] + } imm_bits; + uint32_t value; +}; + +union HWordSignedDataTransferType { + struct reg_bits_type { + uint32_t rm : 4; // [3:0] offset register + uint32_t b4 : 1; // [4] =1 + uint32_t h : 1; // [5] 0=byte; 1=half-word + uint32_t s : 1; // [6] 0=/unsigned; 1=signed + uint32_t b7 : 1; // [7] =1 + uint32_t imm_h : 4; // [11:8] zero/immediate high nibble + uint32_t rd : 4; // [15:12] + uint32_t rn : 4; // [19:16] + uint32_t L : 1; // [20] = 1 load; 0 store + uint32_t W : 1; // [21] = 1 wr addr into base; 0 no write-back + uint32_t reg_imm : 1; // [22] = 0=reg offset; 1=imm offset + uint32_t U : 1; // [23] = 1 add offset; 0 subtruct offset + uint32_t P : 1; // [24] = 1 pre; 0 post + uint32_t zero3 : 3; // [27:25] = 000b + uint32_t cond : 4; // [31:28] + } bits; + uint32_t value; +}; + +union CoprocessorTransferType { + struct bits_type { + uint32_t crm : 4; // [3:0] Coproc. operand register + uint32_t one : 1; // 1b + uint32_t cp_nfo : 3; // [11:5] Coproc. information + uint32_t cp_num : 4; // [11:8] Coproc. number + uint32_t rd : 4; // [15:12] Dest. register + uint32_t crn : 4; // [19:16] Coproc.src/dest reg. + uint32_t L : 1; // [20] 1 load; 0 store + uint32_t mode : 3; // [23:21] Coproc. operation mode + uint32_t opcode : 4; // [27:24] = 1110b + uint32_t cond : 4; // [31:28] + } bits; + uint32_t value; +}; + +union PsrTransferType { + struct reg_bits_type { + uint32_t rm : 4; // [3:0] source reg + uint32_t zero : 8; // [15:4] =00000000b + uint32_t rd : 4; // [15:12] + uint32_t bitmask : 4; // [19:16] + uint32_t b21_20 : 18; // [21:20] =10b + uint32_t Pd : 1; // [23] = 0=CPSR; 1=SPSR_mode + uint32_t b24_23 : 2; // [24:23] = 10b + uint32_t I : 1; // [25] = 1 for immediate instruction + uint32_t b27_26 : 2; // [27:26] = 00b + uint32_t cond : 4; // [31:28] + } reg_bits; + struct imm_bits_type { + uint32_t imm : 8; // [7:0] + uint32_t rotate : 4; // [11:8] shift applied to imm + uint32_t rd : 4; // [15:12] + uint32_t bitmask : 4; // [19:16] + uint32_t b21_20 : 18; // [21:20] =10b + uint32_t Pd : 1; // [23] = 0=CPSR; 1=SPSR_mode + uint32_t b24_23 : 2; // [24:23] = 10b + uint32_t I : 1; // [25] = 1 for immediate instruction + uint32_t b27_26 : 2; // [27:26] = 00b + uint32_t cond : 4; // [31:28] + } imm_bits; + uint32_t value; +}; + +union BranchType { + struct bits_type { + uint32_t offset : 24; // [23:0] offset + uint32_t L : 1; // [24] 0 branch; 1 branch with link + uint32_t opcode : 3; // [27:25] = 101b + uint32_t cond : 4; // [31:28] + } bits; + uint32_t value; +}; + +union BlockDataTransferType { + struct bits_type { + uint32_t reglist : 16; // [15:0] Register list + uint32_t rn : 4; // [19:16] base register + uint32_t L : 1; // [20] 0=load; 1=store + uint32_t W : 1; // [21] 0=no write-back; 1=write adr into base + uint32_t S : 1; // [22] PSR & force user bit + uint32_t U : 1; // [23] 0=down; 1=up adr. increment + uint32_t P : 1; // [24] 0=post; 1=pre-increment + uint32_t b27_25 : 3; // [27:25] = 100b + uint32_t cond : 4; // [31:28] + } bits; + uint32_t value; +}; + +union SignExtendType { + struct bits_type { + uint32_t rm : 4; // [3:0] + uint32_t b7_4 : 4; // [7:4] 0111b + uint32_t sbz : 2; // [9:8] + uint32_t rotate : 2; // [11:10] 0=0; 1=ror8; 2=ror16; 3=ror24 + uint32_t rd : 4; // [15:12] + uint32_t rn : 4; // [19:16] + uint32_t b27_20 : 8; // [27:16] = 01101110b + uint32_t cond : 4; // [31:28] + } bits; + uint32_t value; +}; + +union MulType { + struct mul_bits_type { + uint32_t rm : 4; //[3:0] + uint32_t b7_4 : 4; //[7:4] = 1001b + uint32_t rs : 4; //[11:8] + uint32_t rn : 4; //[15:12] + uint32_t rd : 4; //[19:16] + uint32_t S : 1; //[20] + uint32_t A : 1; //[21] + uint32_t b27_22 : 6; //[27:22] + uint32_t cond : 4; //[31:28] + } bits; + uint32_t value; +}; + +union MulLongType { + struct mull_bits_type { + uint32_t rm : 4; //[3:0] + uint32_t b7_4 : 4; //[7:4] = 1001b + uint32_t rs : 4; //[11:8] + uint32_t rdlo : 4; //[15:12] + uint32_t rdhi : 4; //[19:16] + uint32_t S : 1; //[20] 0=do not alter condition codes + uint32_t A : 1; //[21] 0=mul only; 1=mul + accumulate + uint32_t U : 1; //[22] 0=unsigned; 1=signed + uint32_t b27_22 : 5; //[27:21] = 00001b + uint32_t cond : 4; //[31:28] + } bits; + uint32_t value; +}; + + +union ProgramStatusRegsiterType { + struct bits_type { + uint32_t M : 5; // [4:0] CPU mode: 0x13=supervisor + uint32_t T : 1; // [5] 0=ARM mode; 1=Thumb mode + uint32_t F : 1; // [6] 1=FIQ disable; 0=FIQ enable + uint32_t I : 1; // [7] 1=IRQ disable; 0=IRQ enable + uint32_t A : 1; // [8] 1=disable imprecise data aborts + uint32_t E : 1; // [9] Endianess + uint32_t b15_10 : 6; // [15:10] reserved + uint32_t GE : 4; // [19:16] Greater than or Equal + uint32_t b23_20 : 4; // [23:20] reserved + uint32_t J : 1; // [24] 1=Jazelle ISA; 0=reserved + uint32_t b26_25 : 2; // [26:25] reserved + uint32_t Q : 1; // [27] overflow in DSP instruction + uint32_t V : 1; // [28] overflow flag + uint32_t C : 1; // [29] carry flag + uint32_t Z : 1; // [30] zero flag + uint32_t N : 1; // [31] negative flag + } u; + uint32_t value; +}; + +static const char *const IREGS_NAMES[] = { + "r0", // [0] + "r1", // [1] + "r2", // [2] + "r3", // [3] + "r4", // [4] + "r5", // [5] + "r6", // [6] + "r7", // [7] fp in THUMB mode + "r8", // [8] + "r9", // [9] + "r10", // [10] + "fp", // [11] frame pointer + "r12", // [12] + "sp", // [13] stack pointer + "lr", // [14] link register + "pc", // [15] instruction pointer + "cpsr", // [16] Current Prog. Status Reg (all modes) + "spsr", // [17] Saved Prog. Status Reg +}; + +enum EConditionSuffix { + Cond_EQ, // equal + Cond_NE, // not equal + Cond_CS, // unsigned higer or same + Cond_CC, // unsigned lower + Cond_MI, // negative + Cond_PL, // positive or zero + Cond_VS, // Overflow + Cond_VC, // no overflow + Cond_HI, // unsigned higher + Cond_LS, // unsigned lower or same + Cond_GE, // greater or equal + Cond_LT, // less than + Cond_GT, // greater than + Cond_LE, // less tha or equal + Cond_AL, // always +}; + +enum ERegNames { + Reg_r0, + Reg_r1, // [1] Return address + Reg_r2, // [2] Stack pointer + Reg_r3, // [3] Global pointer + Reg_r4, // [4] Thread pointer + Reg_r5, // [5] Temporaries 0 s3 + Reg_r6, // [6] Temporaries 1 s4 + Reg_r7, // [7] Temporaries 2 s5 + Reg_r8, // [8] s0/fp Saved register/frame pointer + Reg_r9, // [9] Saved register 1 + Reg_r10, // [10] Function argumentes 0 + Reg_r11, // [11] Function argumentes 1 + Reg_fe, // [12] Function argumentes 2 + Reg_sp, // [13] Function argumentes 3 + Reg_lr, // [14] Function argumentes 4 + Reg_pc, // [15] instruction pointer + Reg_cpsr, // [16] Current Prog. Status Reg (all modes) + Reg_spsr, // [17] Saved Prog. Status Reg + Reg_rsrv18, + Reg_rsrv19, + Reg_rsrv20, + Reg_rsrv21, + Reg_rsrv22, + Reg_rsrv23, + Reg_rsrv24, + Reg_rsrv25, + Reg_rsrv26, + Reg_rsrv27, + Reg_rsrv28, + Reg_rsrv29, + Reg_rsrv30, + Reg_rsrv31, + Reg_Total +}; + + +} // namespace debugger + +#endif // __DEBUGGER_COMMON_ARM_ISA_H__
src/cpu_arm_plugin/arm-isa.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/cpu_arm_plugin/arm7tdmi.cpp =================================================================== --- src/cpu_arm_plugin/arm7tdmi.cpp (nonexistent) +++ src/cpu_arm_plugin/arm7tdmi.cpp (revision 5) @@ -0,0 +1,1290 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "api_utils.h" +#include "arm-isa.h" +#include "cpu_arm7_func.h" + +namespace debugger { + +static const uint64_t PREFETCH_OFFSET[InstrModes_Total] = { + 8, + 4 +}; + +/** Data processing default behaviour can be re-implemeted: */ +int ArmDataProcessingInstruction::exec_checked(Reg64Type *payload) { + DataProcessingType u; + u.value = payload->buf32[0]; + uint32_t A = static_cast(R[u.reg_bits.rn]); + uint32_t M; + uint32_t Res; + if (u.imm_bits.I) { + M = imm12(u.imm_bits); + } else { + M = static_cast(R[u.reg_bits.rm]); + M = shift12(u.reg_bits, M, R[u.reg_bits.shift >> 1]); + } + if (do_operation(A, M, &Res)) { + R[u.reg_bits.rd] = Res; + } + if (is_flags_changed(u)) { + set_flags(A, M, Res); + } + return 4; +} + +bool ArmDataProcessingInstruction::is_flags_changed(DataProcessingType u) { + return u.reg_bits.S && u.reg_bits.rd != Reg_pc; +} + +void ArmDataProcessingInstruction::set_flags(uint32_t A, uint32_t M, + uint32_t Res) { + icpu_->setC(0); + icpu_->setZ(Res == 0); + icpu_->setN(Res >> 31); +} + +/** @brief Subtruct specific instruction set + + Specific flags computation with subtraction + */ +class ArmSubInstruction : public ArmDataProcessingInstruction { + public: + ArmSubInstruction(CpuCortex_Functional *icpu, const char *name, + const char *bits) : ArmDataProcessingInstruction(icpu, name, bits) {} + protected: + virtual bool is_inverted() = 0; + virtual bool with_carry() = 0; + virtual EOperationResult op_result() = 0; + + virtual EOperationResult do_operation(uint32_t A, uint32_t M, + uint32_t *pRes) { + if (!is_inverted()) { + *pRes = A - M; + } else { + *pRes = M - A; + } + if (with_carry()) { + *pRes += (icpu_->getC() - 1); + } + return op_result(); + } + + virtual void set_flags(uint32_t A, uint32_t M, uint32_t Res) { + if (is_inverted()) { + uint32_t t1 = A; + A = M; + M = t1; + } + uint32_t C = !(((~A & M) | (M & Res) | (Res & ~A)) >> 31); + uint32_t V = ((A & ~M & ~Res) | (~A & M & Res)) >> 31; + icpu_->setC(C); + icpu_->setV(V); + icpu_->setZ(Res == 0); + icpu_->setN(Res >> 31); + } +}; + +/** @brief addictive specific instruction set + + Specific flags computation with addition + */ +class ArmAddInstruction : public ArmDataProcessingInstruction { + public: + ArmAddInstruction(CpuCortex_Functional *icpu, const char *name, + const char *bits) : ArmDataProcessingInstruction(icpu, name, bits) {} + protected: + virtual EOperationResult op_result() = 0; + virtual bool with_carry() = 0; + + virtual EOperationResult do_operation(uint32_t A, uint32_t M, + uint32_t *pRes) { + *pRes = A + M; + if (with_carry()) { + *pRes += icpu_->getC(); + } + return op_result(); + } + + virtual void set_flags(uint32_t A, uint32_t M, uint32_t Res) { + uint32_t C = ((A & M) | (M & ~Res) | (A & ~Res)) >> 31; + uint32_t V = ((A & M & ~Res) | (~A & ~M & Res)) >> 31; + icpu_->setC(C); + icpu_->setV(V); + icpu_->setZ(Res == 0); + icpu_->setN(Res >> 31); + } +}; + +/** Single memory transfer: LDR, STR +*/ +class SingleDataTransferInstruction : public ArmInstruction { + public: + SingleDataTransferInstruction(CpuCortex_Functional *icpu, const char *name, + const char *bits) : ArmInstruction(icpu, name, bits) {} + + virtual int exec_checked(Reg64Type *payload) { + SingleDataTransferType u; + u.value = payload->buf32[0]; + uint32_t opsz[2] = {4, 1}; + uint64_t off = R[u.imm_bits.rn]; + + if (u.imm_bits.rn == Reg_pc) { + off += PREFETCH_OFFSET[icpu_->getInstrMode()]; + if (u.imm_bits.rd == Reg_pc && !u.imm_bits.I + && (u.imm_bits.imm & 0x1)) { + // DSB, ISB + return 4; + } + } + + if (u.imm_bits.P) { + off += get_increment(u); + if (u.imm_bits.W) { + R[u.imm_bits.rn] = off; + } + } + + trans_.addr = off; + trans_.wstrb = 0; + trans_.xsize = opsz[u.imm_bits.B]; + if (u.imm_bits.L) { + trans_.action = MemAction_Read; + trans_.rpayload.b64[0] = 0; + } else { + trans_.action = MemAction_Write; + trans_.wstrb = (1 << trans_.xsize) - 1; + trans_.wpayload.b64[0] = R[u.imm_bits.rd]; + } + icpu_->dma_memop(&trans_); + + if (!u.imm_bits.P) { + off += get_increment(u); + R[u.imm_bits.rn] = off; + if (u.imm_bits.W) { + /** In the case of post-indexed addressing, the write back bit is + redundant and must be set to zero, since the old base value can be + retained by setting the offset to zero. Therefore post-indexed + data transfers always write back the modified base. The only use of + the W bit in a post-indexed data transfer is in privileged mode + code, where setting the W bit forces non-privileged mode for the + transfer, allowing the operating system to generate a user address + in a system where the memory management hardware makes suitable + use of this hardware. + */ + RISCV_error("Post-index LDR,STR with W=1", 0); + } + } + if (u.imm_bits.L) { + R[u.imm_bits.rd] = trans_.rpayload.b32[0]; + if (u.imm_bits.rd == Reg_pc) { + icpu_->setBranch(R[u.imm_bits.rd]); + } + } + return 4; + } + + protected: + virtual uint64_t get_increment(SingleDataTransferType u) { + uint64_t incr; + if (!u.imm_bits.I) { + incr = u.imm_bits.imm; + } else { + /** + @warning The register specified shift amounts + are not available in this instruction class. + */ + DataProcessingType u2; + u2.value = u.value; + incr = shift12(u2.reg_bits, + static_cast(R[u.reg_bits.rm]), + 0); // !! not available + } + if (!u.reg_bits.U) { + incr = (~incr) + 1; + } + return incr; + } +}; + +/** Block memory transfer: LDM, STM +*/ +class BlockDataTransferInstruction : public ArmInstruction { + public: + BlockDataTransferInstruction(CpuCortex_Functional *icpu, const char *name, + const char *bits) : ArmInstruction(icpu, name, bits) {} + + virtual int exec_checked(Reg64Type *payload) { + BlockDataTransferType u; + uint64_t adrincr[2] = {static_cast(-4), 4}; + u.value = payload->buf32[0]; + uint32_t R15 = (u.bits.reglist >> 15) & 0x1; + int ridx; + // @todo Mode switching depending R15 value!!!! + + trans_.addr = R[u.bits.rn]; + trans_.xsize = 4; + trans_.wstrb = 0; + for (int i = 0; i < 16; i++) { + if (u.bits.L) { + ridx = 15 - i; + } else { + ridx = i; + } + if ((u.bits.reglist & (0x1 << ridx)) == 0) { + continue; + } + if (u.bits.L) { + trans_.action = MemAction_Read; + trans_.rpayload.b64[0] = 0; + } else { + trans_.action = MemAction_Write; + trans_.wstrb = (1 << trans_.xsize) - 1; + trans_.wpayload.b64[0] = R[ridx]; + } + if (u.bits.P) { + trans_.addr += adrincr[u.bits.U]; + if (u.bits.W) { + R[u.bits.rn] = trans_.addr; + } + } + + icpu_->dma_memop(&trans_); + + if (!u.bits.P) { + trans_.addr += adrincr[u.bits.U]; + R[u.bits.rn] = trans_.addr; + } + + if (u.bits.L) { + R[ridx] = trans_.rpayload.b32[0]; + if (ridx == Reg_pc) { + icpu_->setBranch(R[ridx]); + } + } + } + + if (!u.bits.P) { + if (u.bits.W) { + RISCV_error("Post-index LDM,STM with W=1", 0); + } + } + if (u.bits.S) { + // TODO: force user mode + } + return 4; + } +}; + + +/** Halfword and Signed Data Transfer: LDRH/STRH/LDRSB/LDRSH +*/ +class HWordSignedDataTransferInstruction : public ArmInstruction { + public: + HWordSignedDataTransferInstruction(CpuCortex_Functional *icpu, + const char *name, const char *bits) + : ArmInstruction(icpu, name, bits) {} + + virtual int exec_checked(Reg64Type *payload) { + HWordSignedDataTransferType u; + u.value = payload->buf32[0]; + uint32_t opsz[2] = {1, 2}; + uint64_t off = R[u.bits.rn]; + if (u.bits.rn == Reg_pc) { + off += PREFETCH_OFFSET[icpu_->getInstrMode()]; + } + + if (u.bits.P) { + off += get_increment(u); + } + + trans_.addr = off; + trans_.xsize = opsz[u.bits.h]; + trans_.wstrb = 0; + if (u.bits.L) { + trans_.action = MemAction_Read; + trans_.rpayload.b64[0] = 0; + } else { + trans_.action = MemAction_Write; + trans_.wstrb = (1 << trans_.xsize) - 1; + trans_.wpayload.b64[0] = R[u.bits.rd]; + } + icpu_->dma_memop(&trans_); + + if (u.bits.W) { + if (!u.bits.P) { + off += get_increment(u); + } + R[u.bits.rn] = off; + } + if (u.bits.L) { + if (u.bits.h) { + R[u.bits.rd] = trans_.rpayload.b16[0]; + if (u.bits.s) { + R[u.bits.rd] |= EXT_SIGN_16; + } + } else { + R[u.bits.rd] = trans_.rpayload.b8[0]; + if (u.bits.s) { + R[u.bits.rd] |= EXT_SIGN_8; + } + } + if (u.bits.rd == Reg_pc) { + icpu_->setBranch(R[u.bits.rd]); + } + } + return 4; + } + + protected: + virtual uint64_t get_increment(HWordSignedDataTransferType u) { + uint64_t incr; + if (!u.bits.reg_imm) { + incr = (u.bits.imm_h << 4) | u.bits.rm; + } else { + incr = R[u.bits.rm]; + } + if (!u.bits.U) { + incr = (~incr) + 1; + } + return incr; + } +}; + +/** Multiply common */ +class MultiplyInstruction : public ArmInstruction { + public: + MultiplyInstruction(CpuCortex_Functional *icpu, const char *name, + const char *bits) : ArmInstruction(icpu, name, bits) {} + + virtual int exec_checked(Reg64Type *payload) { + MulType u; + u.value = payload->buf32[0]; + uint64_t res = R[u.bits.rm] * R[u.bits.rs]; + if (u.bits.A) { + res += R[u.bits.rn]; + } + R[u.bits.rd] = static_cast(res); + if (u.bits.S) { + icpu_->setC(0); // set meaningless value + icpu_->setZ(R[u.bits.rd] == 0); + icpu_->setN(static_cast(R[u.bits.rd]) >> 31); + } + return 4; + } +}; + +/** Multiply Long common. */ +class MultiplyLongInstruction : public ArmInstruction { + public: + MultiplyLongInstruction(CpuCortex_Functional *icpu, const char *name, + const char *bits) : ArmInstruction(icpu, name, bits) {} + + virtual int exec_checked(Reg64Type *payload) { + MulLongType u; + u.value = payload->buf32[0]; + uint64_t res = 0; + if (u.bits.A) { + res = static_cast(R[u.bits.rdhi]) << 32; + res |= R[u.bits.rdlo]; + } + if (u.bits.S) { + int64_t a = static_cast(R[u.bits.rm]); + int64_t b = static_cast(R[u.bits.rs]); + res = static_cast(static_cast(res) + a * b); + } else { + uint64_t a = R[u.bits.rm]; + uint64_t b = R[u.bits.rs]; + res = res + a * b; + } + R[u.bits.rdlo] = static_cast(res); + R[u.bits.rdhi] = static_cast(res >> 32); + if (u.bits.S) { + icpu_->setC(0); // set to meaningless value + icpu_->setV(0); // set to meaningless value + icpu_->setZ(res == 0); + icpu_->setN(static_cast(res >> 63)); + } + return 4; + } +}; + + +/** + * @brief AND. + */ +static const char *AND_OPCODES[2] = { + "????0000000?????????????????????", + "????0010000?????????????????????" +}; + +class AND : public ArmDataProcessingInstruction { + public: + AND(CpuCortex_Functional *icpu, int opidx) : + ArmDataProcessingInstruction(icpu, "AND", AND_OPCODES[opidx]) {} + protected: + virtual EOperationResult do_operation(uint32_t A, uint32_t M, + uint32_t *pRes) { + *pRes = A & M; + return OP_Write; + } +}; + +/** + * @brief EOR. + */ +static const char *EOR_OPCODES[2] = { + "????0000001?????????????????????", + "????0010001?????????????????????" +}; + +class EOR : public ArmDataProcessingInstruction { + public: + EOR(CpuCortex_Functional *icpu, int opidx) : + ArmDataProcessingInstruction(icpu, "EOR", EOR_OPCODES[opidx]) {} + protected: + virtual EOperationResult do_operation(uint32_t A, uint32_t M, + uint32_t *pRes) { + *pRes = A ^ M; + return OP_Write; + } +}; + +/** + * @brief Subtruct. + */ +static const char *SUB_OPCODES[2] = { + "????0000010?????????????????????", + "????0010010?????????????????????" +}; + +class SUB : public ArmSubInstruction { + public: + SUB(CpuCortex_Functional *icpu, int opidx) : + ArmSubInstruction(icpu, "SUB", SUB_OPCODES[opidx]) {} + protected: + virtual bool is_inverted() { return false; } + virtual bool with_carry() { return false; } + virtual EOperationResult op_result() { return OP_Write; } +}; + +/** + * @brief Subtruct right. + */ +static const char *RSB_OPCODES[2] = { + "????0000011?????????????????????", + "????0010011?????????????????????" +}; + +class RSB : public ArmSubInstruction { + public: + RSB(CpuCortex_Functional *icpu, int opidx) : + ArmSubInstruction(icpu, "RSB", RSB_OPCODES[opidx]) {} + protected: + virtual bool is_inverted() { return true; } + virtual bool with_carry() { return false; } + virtual EOperationResult op_result() { return OP_Write; } +}; + +/** + * @brief Addition. + */ +static const char *ADD_OPCODES[2] = { + "????0000100?????????????????????", + "????0010100?????????????????????" +}; + +class ADD : public ArmAddInstruction { + public: + ADD(CpuCortex_Functional *icpu, int opidx) : + ArmAddInstruction(icpu, "ADD", ADD_OPCODES[opidx]) {} + protected: + virtual EOperationResult op_result() { return OP_Write; } + virtual bool with_carry() { return false; } +}; + +/** + * @brief Addition with carry bit. + */ +static const char *ADC_OPCODES[2] = { + "????0000101?????????????????????", + "????0010101?????????????????????" +}; + +class ADC : public ArmAddInstruction { + public: + ADC(CpuCortex_Functional *icpu, int opidx) : + ArmAddInstruction(icpu, "ADC", ADC_OPCODES[opidx]) {} + protected: + virtual EOperationResult op_result() { return OP_Write; } + virtual bool with_carry() { return true; } +}; + +/** + * @brief Subtruct with carry bit: Op1 - Op2 + C - 1 !!!!!!. + */ +static const char *SBC_OPCODES[2] = { + "????0000110?????????????????????", + "????0010110?????????????????????" +}; + +class SBC : public ArmSubInstruction { + public: + SBC(CpuCortex_Functional *icpu, int opidx) : + ArmSubInstruction(icpu, "SBC", SBC_OPCODES[opidx]) {} + protected: + virtual bool is_inverted() { return false; } + virtual bool with_carry() { return true; } + virtual EOperationResult op_result() { return OP_Write; } +}; + +/** + * @brief Subtruct right with carry bit: Op2 - Op1 + C - 1 !!!!. + */ +static const char *RSC_OPCODES[2] = { + "????0000111?????????????????????", + "????0010111?????????????????????" +}; + +class RSC : public ArmSubInstruction { + public: + RSC(CpuCortex_Functional *icpu, int opidx) : + ArmSubInstruction(icpu, "RSC", RSC_OPCODES[opidx]) {} + protected: + virtual bool is_inverted() { return true; } + virtual bool with_carry() { return true; } + virtual EOperationResult op_result() { return OP_Write; } +}; + +/** + * @brief Set condition codes on Op1 AND Op2. + * S-flag must be set otherwise it can be MOVW instruction + */ + static const char *TST_OPCODES[2] = { + "????00010001????????????????????", + "????00110001????????????????????" +}; + +class TST : public ArmDataProcessingInstruction { + public: + TST(CpuCortex_Functional *icpu, int opidx) : + ArmDataProcessingInstruction(icpu, "TST", TST_OPCODES[opidx]) {} + protected: + virtual EOperationResult do_operation(uint32_t A, uint32_t M, + uint32_t *pRes) { + *pRes = A & M; + return OP_Drop; + } +}; + +/** + * @brief Set condition codes on Op1 EOR Op2. + */ +static const char *TEQ_OPCODES[2] = { + "????0001001?????????????????????", + "????0011001?????????????????????" +}; + +class TEQ : public ArmDataProcessingInstruction { + public: + TEQ(CpuCortex_Functional *icpu, int opidx) : + ArmDataProcessingInstruction(icpu, "TEQ", TEQ_OPCODES[opidx]) {} + protected: + virtual EOperationResult do_operation(uint32_t A, uint32_t M, + uint32_t *pRes) { + *pRes = A ^ M; + return OP_Drop; + } +}; + +/** + * @brief Set condition codes on Op1 - Op2. + */ +static const char *CMP_OPCODES[2] = { + "????0001010?????????????????????", + "????0011010?????????????????????" +}; + +class CMP : public ArmSubInstruction { + public: + CMP(CpuCortex_Functional *icpu, int opidx) : + ArmSubInstruction(icpu, "CMP", CMP_OPCODES[opidx]) {} + protected: + virtual bool is_inverted() { return false; } + virtual bool with_carry() { return false; } + virtual EOperationResult op_result() { return OP_Drop; } +}; + +/** + * @brief Set condition codes on Op1 + Op2. + */ +static const char *CMN_OPCODES[2] = { + "????0001011?????????????????????", + "????0011011?????????????????????" +}; + +class CMN : public ArmAddInstruction { + public: + CMN(CpuCortex_Functional *icpu, int opidx) : + ArmAddInstruction(icpu, "CMN", CMN_OPCODES[opidx]) {} + protected: + virtual bool with_carry() { return false; } + virtual EOperationResult op_result() { return OP_Drop; } +}; + +/** + * @brief OR + */ +static const char *ORR_OPCODES[2] = { + "????0001100?????????????????????", + "????0011100?????????????????????" +}; + +class ORR : public ArmDataProcessingInstruction { + public: + ORR(CpuCortex_Functional *icpu, int opidx) : + ArmDataProcessingInstruction(icpu, "ORR", ORR_OPCODES[opidx]) {} + protected: + virtual EOperationResult do_operation(uint32_t A, uint32_t M, + uint32_t *pRes) { + *pRes = A | M; + return OP_Write; + } +}; + +/** + * @brief Move data: Rd = Op2 + */ +static const char *MOV_OPCODES[2] = { + "????0001101?????????????????????", + "????0011101?????????????????????" +}; + +class MOV : public ArmDataProcessingInstruction { + public: + MOV(CpuCortex_Functional *icpu, int opidx) : + ArmDataProcessingInstruction(icpu, "MOV", MOV_OPCODES[opidx]) {} + protected: + virtual EOperationResult do_operation(uint32_t A, uint32_t M, + uint32_t *pRes) { + *pRes = M; + return OP_Write; + } +}; + +/** Move Top writes an immediate value to the top halfword of the destination + register. It does not affect the contents of the bottom halfword. */ +class MOVT : public ArmInstruction { + public: + MOVT(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "MOVT", "????00110100????????????????????") {} + protected: + virtual int exec_checked(Reg64Type *payload) { + DataProcessingType u; + u.value = payload->buf32[0]; + uint32_t imm16 = (u.mov_bits.imm4 << 12) | u.mov_bits.imm12; + R[u.mov_bits.rd] &= ~0xFFFF0000; + R[u.mov_bits.rd] |= (imm16 << 16); + return 4; + } +}; + +/** This new variant of MOV (immediate) writes a 16-bit immediate + value to the destination register */ +class MOVW : public ArmInstruction { + public: + MOVW(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "MOVW", "????00110000????????????????????") {} + protected: + virtual int exec_checked(Reg64Type *payload) { + DataProcessingType u; + u.value = payload->buf32[0]; + uint32_t imm16 = (u.mov_bits.imm4 << 12) | u.mov_bits.imm12; + R[u.mov_bits.rd] &= ~0xFFFF; + R[u.mov_bits.rd] |= imm16; + return 4; + } +}; + +/** Rd:=Rm*Rs. */ +class MUL : public MultiplyInstruction { + public: + MUL(CpuCortex_Functional *icpu) : MultiplyInstruction(icpu, + "MUL", "????0000000?????????????1001????") {} +}; + +/** Multiply and accumulate: Rd:=Rm*Rs+Rn */ +class MLA : public MultiplyInstruction { + public: + MLA(CpuCortex_Functional *icpu) : MultiplyInstruction(icpu, + "MLA", "????0000001?????????????1001????") {} +}; + +/** Unsigned Multiply Long */ +class UMULL : public MultiplyLongInstruction { + public: + UMULL(CpuCortex_Functional *icpu) : MultiplyLongInstruction(icpu, + "UMULL", "????0000100?????????????1001????") {} +}; + +/** Unsigned Multiply ^ Accumulate Long */ +class UMLAL : public MultiplyLongInstruction { + public: + UMLAL(CpuCortex_Functional *icpu) : MultiplyLongInstruction(icpu, + "UMLAL", "????0000101?????????????1001????") {} +}; + +/** Signed Multiply Long */ +class SMULL : public MultiplyLongInstruction { + public: + SMULL(CpuCortex_Functional *icpu) : MultiplyLongInstruction(icpu, + "SMULL", "????0000110?????????????1001????") {} +}; + +/** Signed Multiply ^ Accumulate Long */ +class SMLAL : public MultiplyLongInstruction { + public: + SMLAL(CpuCortex_Functional *icpu) : MultiplyLongInstruction(icpu, + "SMLAL", "????0000111?????????????1001????") {} +}; + +/** + * @brief Bit clear: AND NOT + */ +static const char *BIC_OPCODES[2] = { + "????0001110?????????????????????", + "????0011110?????????????????????" +}; + +class BIC : public ArmDataProcessingInstruction { + public: + BIC(CpuCortex_Functional *icpu, int opidx) : + ArmDataProcessingInstruction(icpu, "BIC", BIC_OPCODES[opidx]) {} + protected: + virtual EOperationResult do_operation(uint32_t A, uint32_t M, + uint32_t *pRes) { + *pRes = A & ~M; + return OP_Write; + } +}; + +/** + * @brief Move inverted data: Rd = NOT Op2 + */ +static const char *MVN_OPCODES[2] = { + "????0001111?????????????????????", + "????0011111?????????????????????" +}; + +class MVN : public ArmDataProcessingInstruction { + public: + MVN(CpuCortex_Functional *icpu, int opidx) : + ArmDataProcessingInstruction(icpu, "MVN", MVN_OPCODES[opidx]) {} + protected: + virtual EOperationResult do_operation(uint32_t A, uint32_t M, + uint32_t *pRes) { + *pRes = ~M; + return OP_Write; + } +}; + +/** Branch */ +class B : public ArmInstruction { +public: + B(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "B", "????1010????????????????????????") {} + + virtual int exec_checked(Reg64Type *payload) { + BranchType u; + u.value = payload->buf32[0]; + uint32_t off = u.bits.offset; + if ((u.value >> 23) & 0x1) { + off |= 0xFF000000; + } + off = static_cast( + R[Reg_pc] + (off << 2) + PREFETCH_OFFSET[icpu_->getInstrMode()]); + R[Reg_pc] = off; + icpu_->setBranch(off); + return 4; + } +}; + +/** Branch with Link */ +class BL : public ArmInstruction { +public: + BL(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "BL", "????1011????????????????????????") {} + + virtual int exec_checked(Reg64Type *payload) { + BranchType u; + u.value = payload->buf32[0]; + R[Reg_lr] = R[Reg_pc] + 4; + uint32_t off = u.bits.offset; + if ((u.value >> 23) & 0x1) { + off |= 0xFF000000; + } + off = static_cast( + R[Reg_pc] + (off << 2) + PREFETCH_OFFSET[icpu_->getInstrMode()]); + R[Reg_pc] = off; + icpu_->setBranch(off); + return 4; + } +}; + +/** Branch and Exchange */ +class BX : public ArmInstruction { +public: + BX(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "BX", "????000100101111111111110001????") {} + + virtual int exec_checked(Reg64Type *payload) { + BranchType u; + u.value = payload->buf32[0]; + uint32_t off = static_cast(R[u.bits.offset & 0xf]); + if (off & 0x1) { + icpu_->setInstrMode(THUMB_mode); + } else { + icpu_->setInstrMode(ARM_mode); + } + R[Reg_pc] = off; + icpu_->setBranch(off); + return 4; + } +}; + +/** Load word pre-adding immediate offset to base register */ +static const char *LDR_OPCODES[4] = { + "????0100???1????????????????????", // immedaiate, post incr + "????0101???1????????????????????", // immedaiate, pre incr + "????0110???1????????????????????", // shift reg, post incr + "????0111???1????????????????????", // shift reg, pre incr +}; + +class LDR : public SingleDataTransferInstruction { +public: + LDR(CpuCortex_Functional *icpu, int opidx) : + SingleDataTransferInstruction(icpu, "LDR", LDR_OPCODES[opidx]) {} +}; + +/** Load Signed Byte */ +static const char *LDRSB_OPCODES[4] = { + "????0000???1????????????1101????", // post incr + "????0001???1????????????1101????", // pre incr +}; + +class LDRSB : public HWordSignedDataTransferInstruction { +public: + LDRSB(CpuCortex_Functional *icpu, int opidx) : + HWordSignedDataTransferInstruction(icpu, "LDRSB", LDRSB_OPCODES[opidx]) + {} +}; + +/** Load Unsigned Half-Word */ +static const char *LDRH_OPCODES[4] = { + "????0000???1????????????1011????", // post incr + "????0001???1????????????1011????", // pre incr +}; + +class LDRH : public HWordSignedDataTransferInstruction { +public: + LDRH(CpuCortex_Functional *icpu, int opidx) : + HWordSignedDataTransferInstruction(icpu, "LDRH", LDRH_OPCODES[opidx]) + {} +}; + +/** Load Signed Half-word */ +static const char *LDRSH_OPCODES[4] = { + "????0000???1????????????1111????", // post incr + "????0001???1????????????1111????", // pre incr +}; + +class LDRSH : public HWordSignedDataTransferInstruction { +public: + LDRSH(CpuCortex_Functional *icpu, int opidx) : + HWordSignedDataTransferInstruction(icpu, "LDRSH", LDRSB_OPCODES[opidx]) + {} +}; + +/** Load Block data */ +static const char *LDM_OPCODES[4] = { + "????1000???1????????????????????", // post incr + "????1001???1????????????????????", // pre incr +}; + +class LDM : public BlockDataTransferInstruction { + public: + LDM(CpuCortex_Functional *icpu, int opidx) : + BlockDataTransferInstruction(icpu, "LDM", LDM_OPCODES[opidx]) {} +}; + + + +/** Store word */ +static const char *STR_OPCODES[4] = { + "????0100?0?0????????????????????", // immedaiate, post incr + "????0101?0?0????????????????????", // immedaiate, pre incr + "????0110?0?0????????????????????", // shift reg, post incr + "????0111?0?0????????????????????", // shift reg, pre incr +}; + +class STR : public SingleDataTransferInstruction { +public: + STR(CpuCortex_Functional *icpu, int opidx) : + SingleDataTransferInstruction(icpu, "STR", STR_OPCODES[opidx]) {} +}; + +/** Store Byte */ +static const char *STRB_OPCODES[4] = { + "????0100?1?0????????????????????", // immedaiate, post incr + "????0101?1?0????????????????????", // immedaiate, pre incr + "????0110?1?0????????????????????", // shift reg, post incr + "????0111?1?0????????????????????", // shift reg, pre incr +}; + +class STRB : public SingleDataTransferInstruction { +public: + STRB(CpuCortex_Functional *icpu, int opidx) : + SingleDataTransferInstruction(icpu, "STRB", STRB_OPCODES[opidx]) {} +}; + +/** Store Half-Word */ +static const char *STRH_OPCODES[4] = { + "????0000???0????????????1?11????", // post incr + "????0001???0????????????1?11????", // pre incr +}; + +class STRH : public HWordSignedDataTransferInstruction { +public: + STRH(CpuCortex_Functional *icpu, int opidx) : + HWordSignedDataTransferInstruction(icpu, "STRH", STRH_OPCODES[opidx]) + {} +}; + +/** Store Block data */ +static const char *STM_OPCODES[4] = { + "????1000???0????????????????????", // post incr + "????1001???0????????????????????", // pre incr +}; + +class STM : public BlockDataTransferInstruction { + public: + STM(CpuCortex_Functional *icpu, int opidx) : + BlockDataTransferInstruction(icpu, "STM", STM_OPCODES[opidx]) {} +}; + +/** Move from coprocessor to ARM7TDMI-S register (L=1) */ +class MRC : public ArmInstruction { + public: + MRC(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "MRC", "????1110???1???????????????1????") {} + + virtual int exec_checked(Reg64Type *payload) { + CoprocessorTransferType u; + u.value = payload->buf32[0]; + return 4; + } +}; + +/** Move from ARM7TDMI-S register to coprocessor (L=0) */ +class MCR : public ArmInstruction { + public: + MCR(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "MRC", "????1110???0???????????????1????") {} + + virtual int exec_checked(Reg64Type *payload) { + CoprocessorTransferType u; + u.value = payload->buf32[0]; + return 4; + } +}; + +/** + * @brief Transfer register to PSR flags. + */ +static const char *MSR_OPCODES[2] = { + "????00010?10????1111????????????", + "????00110?10????1111????????????" +}; + +class MSR : public ArmInstruction { +public: + MSR(CpuCortex_Functional *icpu, int opidx) : + ArmInstruction(icpu, "MSR", MSR_OPCODES[opidx]) {} + + virtual int exec_checked(Reg64Type *payload) { + PsrTransferType u; + u.value = payload->buf32[0]; + return 4; + } +}; + +class MRS : public ArmInstruction { +public: + MRS(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "MRS", "????00010?001111????000000000000") {} + + virtual int exec_checked(Reg64Type *payload) { + PsrTransferType u; + u.value = payload->buf32[0]; + return 4; + } +}; + +class NOP : public ArmInstruction { +public: + NOP(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "NOP", "????0011001000001111000000000000") {} + + virtual int exec_checked(Reg64Type *payload) { + return 4; + } +}; + +/** Bytes zero-extending + UXTB extracts an 8-bit value from a register and zero extends it to 32 bits. + You can specify a rotation by 0, 8, 16, or 24 bits before extracting + the 8-bit value. + */ +class UXTB : public ArmInstruction { +public: + UXTB(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "UXTB", "????011011101111????????0111????") {} + + virtual int exec_checked(Reg64Type *payload) { + SignExtendType u; + u.value = payload->buf32[0]; + uint64_t t1 = (R[u.bits.rm] & 0xFFFFFFFF) >> (8*u.bits.rotate); + t1 = (R[u.bits.rm] << (32 - 8*u.bits.rotate)) | t1; + t1 &= 0xFF; + R[u.bits.rd] = static_cast(t1); + return 4; + } +}; + +/** */ +class UXTAB : public ArmInstruction { +public: + UXTAB(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "UXTAB", "????01101110????????????0111????") {} + + virtual int exec_checked(Reg64Type *payload) { + SignExtendType u; + u.value = payload->buf32[0]; + uint64_t t1 = (R[u.bits.rm] & 0xFFFFFFFF) >> (8*u.bits.rotate); + t1 = (R[u.bits.rm] << (32 - 8*u.bits.rotate)) | t1; + t1 &= 0xFF; + R[u.bits.rd] = R[u.bits.rn] + static_cast(t1); + return 4; + } +}; + +/** UXTB16 extracts two 8-bit values from a register and zero extends them + to 16 bits each. You can specify a rotation by 0, 8, 16, or 24 bits before + extracting the 8-bit values. + */ +class UXTB16 : public ArmInstruction { +public: + UXTB16(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "UXTB16", "????011011001111????????0111????") {} + + virtual int exec_checked(Reg64Type *payload) { + SignExtendType u; + u.value = payload->buf32[0]; + uint64_t t1 = (R[u.bits.rm] & 0xFFFFFFFF) >> (8*u.bits.rotate); + t1 = (R[u.bits.rm] << (32 - 8*u.bits.rotate)) | t1; + t1 &= 0x00FF00FF; + R[u.bits.rd] = static_cast(t1); + return 4; + } +}; + +/** UXTAB16 extracts two 8-bit values from a register, zero extends them + to 16 bits each, and adds the results to the two values from another + register. You can specify a rotation by 0, 8, 16, or 24 bits before + extracting the 8-bit values. + */ +class UXTAB16 : public ArmInstruction { +public: + UXTAB16(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "UXTAB16", "????01101100????????????0111????") {} + + virtual int exec_checked(Reg64Type *payload) { + SignExtendType u; + u.value = payload->buf32[0]; + uint64_t t1 = (R[u.bits.rm] & 0xFFFFFFFF) >> (8*u.bits.rotate); + t1 = (R[u.bits.rm] << (32 - 8*u.bits.rotate)) | t1; + uint32_t a = (R[u.bits.rd] & 0xFFFF) + (t1 & 0xFF); + uint32_t b = ((R[u.bits.rd] >> 16) & 0xFFFF) + ((t1 >> 16) & 0xFF); + R[u.bits.rd] = (b << 16) | a; + return 4; + } +}; + + +/** UXTH extracts a 16-bit value from a register and zero extends it + to 32 bits. You can specify a rotation by 0, 8, 16, or 24 bits before + extracting the 16-bit value. + */ +class UXTH : public ArmInstruction { +public: + UXTH(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "UXTH", "????011011111111????????0111????") {} + + virtual int exec_checked(Reg64Type *payload) { + SignExtendType u; + u.value = payload->buf32[0]; + uint64_t t1 = (R[u.bits.rm] & 0xFFFFFFFF) >> (8*u.bits.rotate); + t1 = (R[u.bits.rm] << (32 - 8*u.bits.rotate)) | t1; + t1 &= 0xFFFF; + R[u.bits.rd] = static_cast(t1); + return 4; + } +}; + +/** UXTAH extracts a 16-bit value from a register, zero extends it to 32 bits, + and adds the result to a value in another register. You can specify a + rotation by 0, 8, 16, or 24 bits before extracting the 16-bit value. + */ +class UXTAH : public ArmInstruction { +public: + UXTAH(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "UXTAH", "????01101111????????????0111????") {} + + virtual int exec_checked(Reg64Type *payload) { + SignExtendType u; + u.value = payload->buf32[0]; + uint64_t t1 = (R[u.bits.rm] & 0xFFFFFFFF) >> (8*u.bits.rotate); + t1 = (R[u.bits.rm] << (32 - 8*u.bits.rotate)) | t1; + t1 &= 0xFFFF; + R[u.bits.rd] = R[u.bits.rn] + static_cast(t1); + return 4; + } +}; + + +/** + * @brief SWI (software breakpoint instruction) + * + */ +class SWI : public ArmInstruction { + public: + SWI(CpuCortex_Functional *icpu) : + ArmInstruction(icpu, "SWI", "????1110???1???????????????1????") {} + + virtual int exec_checked(Reg64Type *payload) { + icpu_->raiseSoftwareIrq(); + return 4; + } +}; + + + +void CpuCortex_Functional::addArm7tmdiIsa() { + + // Arm V6 instructions: + // CPS, SRS, RFE + // REV, REV16, REVSH + // SETEND + // LDREX, STREX + // SXTB, SXTH, UXTB, UXTH + addSupportedInstruction(new UXTB(this)); // same opcode as STRB + addSupportedInstruction(new UXTAB(this)); + addSupportedInstruction(new UXTB16(this)); // rn=1111b + addSupportedInstruction(new UXTAB16(this)); // rn=????b + addSupportedInstruction(new UXTH(this)); // rn=1111b + addSupportedInstruction(new UXTAH(this)); // rn=???? + + // use the same as opcodes TEQ, TST, CMN and CMP without S-flag + // and must be registered first. + addSupportedInstruction(new BX(this)); // use TST,MSR opcode + addSupportedInstruction(new NOP(this)); // use MSR opcode + addSupportedInstruction(new MOVT(this)); + addSupportedInstruction(new MOVW(this)); + addSupportedInstruction(new MUL(this)); + addSupportedInstruction(new MLA(this)); + addSupportedInstruction(new UMULL(this)); + addSupportedInstruction(new UMLAL(this)); + addSupportedInstruction(new SMULL(this)); + addSupportedInstruction(new SMLAL(this)); + addSupportedInstruction(new MRS(this)); + addSupportedInstruction(new MSR(this, 0)); + addSupportedInstruction(new MSR(this, 1)); + + addSupportedInstruction(new AND(this, 0)); + addSupportedInstruction(new AND(this, 1)); + addSupportedInstruction(new EOR(this, 0)); + addSupportedInstruction(new EOR(this, 1)); + addSupportedInstruction(new SUB(this, 0)); + addSupportedInstruction(new SUB(this, 1)); + addSupportedInstruction(new RSB(this, 0)); + addSupportedInstruction(new RSB(this, 1)); + addSupportedInstruction(new ADD(this, 0)); + addSupportedInstruction(new ADD(this, 1)); + addSupportedInstruction(new ADC(this, 0)); + addSupportedInstruction(new ADC(this, 1)); + addSupportedInstruction(new SBC(this, 0)); + addSupportedInstruction(new SBC(this, 1)); + addSupportedInstruction(new RSC(this, 0)); + addSupportedInstruction(new RSC(this, 1)); + addSupportedInstruction(new TST(this, 0)); + addSupportedInstruction(new TST(this, 1)); + addSupportedInstruction(new TEQ(this, 0)); + addSupportedInstruction(new TEQ(this, 1)); + addSupportedInstruction(new CMP(this, 0)); + addSupportedInstruction(new CMP(this, 1)); + addSupportedInstruction(new CMN(this, 0)); + addSupportedInstruction(new CMN(this, 1)); + addSupportedInstruction(new ORR(this, 0)); + addSupportedInstruction(new ORR(this, 1)); + addSupportedInstruction(new MOV(this, 0)); + addSupportedInstruction(new MOV(this, 1)); + addSupportedInstruction(new BIC(this, 0)); + addSupportedInstruction(new BIC(this, 1)); + addSupportedInstruction(new MVN(this, 0)); + addSupportedInstruction(new MVN(this, 1)); + addSupportedInstruction(new B(this)); + addSupportedInstruction(new BL(this)); + addSupportedInstruction(new LDR(this, 0)); + addSupportedInstruction(new LDR(this, 1)); + addSupportedInstruction(new LDR(this, 2)); + addSupportedInstruction(new LDR(this, 3)); + addSupportedInstruction(new LDRSB(this, 0)); + addSupportedInstruction(new LDRSB(this, 1)); + addSupportedInstruction(new LDRH(this, 0)); + addSupportedInstruction(new LDRH(this, 1)); + addSupportedInstruction(new LDRSH(this, 0)); + addSupportedInstruction(new LDRSH(this, 1)); + addSupportedInstruction(new LDM(this, 0)); + addSupportedInstruction(new LDM(this, 1)); + addSupportedInstruction(new STR(this, 0)); + addSupportedInstruction(new STR(this, 1)); + addSupportedInstruction(new STR(this, 2)); + addSupportedInstruction(new STR(this, 3)); + addSupportedInstruction(new STRB(this, 0)); + addSupportedInstruction(new STRB(this, 1)); + addSupportedInstruction(new STRB(this, 2)); + addSupportedInstruction(new STRB(this, 3)); + addSupportedInstruction(new STRH(this, 0)); + addSupportedInstruction(new STRH(this, 1)); + addSupportedInstruction(new STM(this, 0)); + addSupportedInstruction(new STM(this, 1)); + addSupportedInstruction(new MCR(this)); + addSupportedInstruction(new MRC(this)); + addSupportedInstruction(new SWI(this)); +} + +} // namespace debugger
src/cpu_arm_plugin/arm7tdmi.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/cpu_arm_plugin/cpu_arm7_func.cpp =================================================================== --- src/cpu_arm_plugin/cpu_arm7_func.cpp (nonexistent) +++ src/cpu_arm_plugin/cpu_arm7_func.cpp (revision 5) @@ -0,0 +1,141 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include "cpu_arm7_func.h" + +namespace debugger { + +CpuCortex_Functional::CpuCortex_Functional(const char *name) : + CpuGeneric(name), + portRegs_(this, "regs", 0x8000, Reg_Total), + portSavedRegs_(this, "savedregs", 0, Reg_Total) { + registerInterface(static_cast(this)); + registerAttribute("VectorTable", &vectorTable_); + p_psr_ = reinterpret_cast( + &portRegs_.getp()[Reg_cpsr]); +} + +CpuCortex_Functional::~CpuCortex_Functional() { +} + +void CpuCortex_Functional::postinitService() { + // Supported instruction sets: + for (int i = 0; i < INSTR_HASH_TABLE_SIZE; i++) { + listInstr_[i].make_list(0); + } + addArm7tmdiIsa(); + + // Power-on + reset(false); + + CpuGeneric::postinitService(); +} + +unsigned CpuCortex_Functional::addSupportedInstruction( + ArmInstruction *instr) { + AttributeType tmp(instr); + listInstr_[instr->hash()].add_to_list(&tmp); + return 0; +} + +void CpuCortex_Functional::handleTrap() { + if (interrupt_pending_ == 0) { + return; + } + npc_.setValue(0 + 4*0); + interrupt_pending_ = 0; +} + +void CpuCortex_Functional::reset(bool active) { + CpuGeneric::reset(active); + portRegs_.reset(); + estate_ = CORE_Halted; +} + +GenericInstruction *CpuCortex_Functional::decodeInstruction(Reg64Type *cache) { + ArmInstruction *instr = NULL; + int hash_idx = hash32(cacheline_[0].buf32[0]); + for (unsigned i = 0; i < listInstr_[hash_idx].size(); i++) { + instr = static_cast( + listInstr_[hash_idx][i].to_iface()); + if (instr->parse(cacheline_[0].buf32)) { + break; + } + instr = NULL; + } + portRegs_.getp()[Reg_pc].val = getPC(); + return instr; +} + +void CpuCortex_Functional::generateIllegalOpcode() { + //raiseSignal(EXCEPTION_InstrIllegal); + RISCV_error("Illegal instruction at 0x%08" RV_PRI64 "x", getPC()); +} + +void CpuCortex_Functional::trackContextStart() { + if (reg_trace_file == 0) { + return; + } + /** Save previous reg values to find modification after exec() */ + uint64_t *dst = portSavedRegs_.getpR64(); + uint64_t *src = portRegs_.getpR64(); + memcpy(dst, src, Reg_Total*sizeof(uint64_t)); +} + +void CpuCortex_Functional::trackContextEnd() { + if (reg_trace_file == 0) { + return; + } + int sz; + char tstr[1024]; + const char *pinstrname = "unknown"; + if (instr_) { + pinstrname = instr_->name(); + } + sz = RISCV_sprintf(tstr, sizeof(tstr),"%8I64d [%08x]: %8s ", + step_cnt_, pc_.getValue().buf32[0], + pinstrname); + + bool reg_changed = false; + uint64_t *prev = portSavedRegs_.getpR64(); + uint64_t *cur = portRegs_.getpR64(); + for (int i = 0; i < Reg_Total; i++) { + if (prev[i] != cur[i]) { + reg_changed = true; + sz += RISCV_sprintf(&tstr[sz], sizeof(tstr) - sz, + "%3s <= %016I64x ", + IREGS_NAMES[i], cur[i]); + } + } + if (instr_ && !reg_changed) { + sz += RISCV_sprintf(&tstr[sz], sizeof(tstr) - sz, "-", NULL); + } + (*reg_trace_file) << tstr << "\n"; + reg_trace_file->flush(); +} + +void CpuCortex_Functional::raiseSignal(int idx) { + RISCV_error("Raise unsupported signal %d", idx); +} + +void CpuCortex_Functional::lowerSignal(int idx) { + interrupt_pending_ &= ~(1 << idx); + RISCV_error("Lower unsupported signal %d", idx); +} + +} // namespace debugger +
src/cpu_arm_plugin/cpu_arm7_func.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/cpu_arm_plugin/cpu_arm7_func.h =================================================================== --- src/cpu_arm_plugin/cpu_arm7_func.h (nonexistent) +++ src/cpu_arm_plugin/cpu_arm7_func.h (revision 5) @@ -0,0 +1,90 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEBUGGER_CPU_ARM7_FUNCTIONAL_H__ +#define __DEBUGGER_CPU_ARM7_FUNCTIONAL_H__ + +#include "arm-isa.h" +#include "instructions.h" +#include "generic/cpu_generic.h" +#include "coreservices/icpuarm.h" + +namespace debugger { + +class CpuCortex_Functional : public CpuGeneric, + public ICpuArm { + public: + explicit CpuCortex_Functional(const char *name); + virtual ~CpuCortex_Functional(); + + /** IService interface */ + virtual void postinitService(); + + /** IResetListener itnterface */ + virtual void reset(bool active); + + /** ICpuGeneric interface */ + virtual void raiseSignal(int idx); + virtual void lowerSignal(int idx); + virtual void raiseSoftwareIrq() {} + virtual uint64_t getIrqAddress(int idx) { return 0; } + + /** ICpuArm */ + virtual uint32_t getZ() { return p_psr_->u.Z; } + virtual void setZ(uint32_t z) { p_psr_->u.Z = z; } + virtual uint32_t getC() { return p_psr_->u.C; } + virtual void setC(uint32_t c) { p_psr_->u.C = c; } + virtual uint32_t getN() { return p_psr_->u.N; } + virtual void setN(uint32_t n) { p_psr_->u.N = n; } + virtual uint32_t getV() { return p_psr_->u.V; } + virtual void setV(uint32_t v) { p_psr_->u.V = v; } + + // Common River methods shared with instructions: + uint64_t *getpRegs() { return portRegs_.getpR64(); } + + protected: + /** CpuGeneric common methods */ + virtual EEndianessType endianess() { return LittleEndian; } + virtual GenericInstruction *decodeInstruction(Reg64Type *cache); + virtual void generateIllegalOpcode(); + virtual void handleTrap(); + /** Tack Registers changes during execution */ + virtual void trackContextStart(); + /** // Stop tracking and write trace file */ + virtual void trackContextEnd(); + + void addArm7tmdiIsa(); + unsigned addSupportedInstruction(ArmInstruction *instr); + uint32_t hash32(uint32_t val) { return (val >> 24) & 0xf; } + + private: + AttributeType listExtISA_; + AttributeType vendorID_; + AttributeType vectorTable_; + + static const int INSTR_HASH_TABLE_SIZE = 1 << 4; + AttributeType listInstr_[INSTR_HASH_TABLE_SIZE]; + + GenericReg64Bank portRegs_; + GenericReg64Bank portSavedRegs_; + ProgramStatusRegsiterType *p_psr_; +}; + +DECLARE_CLASS(CpuCortex_Functional) + +} // namespace debugger + +#endif // __DEBUGGER_CPU_RISCV_FUNCTIONAL_H__
src/cpu_arm_plugin/cpu_arm7_func.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/cpu_arm_plugin/instructions.cpp =================================================================== --- src/cpu_arm_plugin/instructions.cpp (nonexistent) +++ src/cpu_arm_plugin/instructions.cpp (revision 5) @@ -0,0 +1,129 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "api_utils.h" +#include "arm-isa.h" +#include "instructions.h" +#include "cpu_arm7_func.h" + +namespace debugger { + +ArmInstruction::ArmInstruction(CpuCortex_Functional *icpu, const char *name, + const char *bits) { + icpu_ = icpu; + R = icpu->getpRegs(); + name_.make_string(name); + mask_ = 0; + opcode_ = 0; + for (int i = 0; i < 32; i++) { + switch (bits[i]) { + case '0': + break; + case '1': + opcode_ |= (1 << (31 - i)); + break; + case '?': + mask_ |= (1 << (31 - i)); + break; + default:; + } + } + mask_ ^= ~0; +} + +IFace *ArmInstruction::getInterface(const char *name) { + return icpu_->getInterface(name); +} + +int ArmInstruction::exec(Reg64Type *payload) { +#if 1 + if (icpu_->getPC() == 0xf24) { + bool st = true; + } +#endif + if (check_cond(payload->buf32[0] >> 28)) { + return exec_checked(payload); + } + return 4; +} + +bool ArmInstruction::check_cond(uint32_t cond) { + switch (cond) { + case Cond_EQ: + return icpu_->getZ() == 1; + case Cond_NE: + return icpu_->getZ() == 0; + case Cond_CS: + return icpu_->getC() == 1; + case Cond_CC: + return icpu_->getC() == 0; + case Cond_MI: + return icpu_->getN() == 1; + case Cond_PL: + return icpu_->getN() == 0; + case Cond_VS: + return icpu_->getV() == 1; + case Cond_VC: + return icpu_->getV() == 0; + case Cond_HI: + return icpu_->getC() && !icpu_->getZ(); + case Cond_LS: + return !icpu_->getC() || icpu_->getZ(); + case Cond_GE: + return !(icpu_->getN() ^ icpu_->getV()); + case Cond_LT: + return (icpu_->getN() ^ icpu_->getV()) == 1; + case Cond_GT: + return !icpu_->getZ() && !(icpu_->getN() ^ icpu_->getV()); + case Cond_LE: + return icpu_->getZ() || (icpu_->getN() ^ icpu_->getV()); + default:; + return true; + } +} + +uint32_t ArmInstruction::shift12(DataProcessingType::reg_bits_type instr, + uint32_t reg, uint64_t Rs) { + uint32_t ret = reg; + uint32_t shift = instr.shift; + if (instr.sh_sel) { + shift = static_cast(Rs & 0x1f); + } + switch (instr.sh_type) { + case 0: // logical left + ret <<= shift; + break; + case 1: // logical right + ret >>= shift; + break; + case 2: // arith. right + ret = + static_cast((static_cast(ret) >> shift)); + break; + case 3: // rotate right + ret = (ret >> shift) | (ret << (32 - shift)); + break; + } + return ret; +} + +uint32_t ArmInstruction::imm12(DataProcessingType::imm_bits_type instr) { + uint32_t rsh = 2*instr.rotate; + uint32_t imm = (instr.imm >> rsh) | (instr.imm << (32 - rsh)); + return imm; +} + +} // namespace debugger
src/cpu_arm_plugin/instructions.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/cpu_arm_plugin/instructions.h =================================================================== --- src/cpu_arm_plugin/instructions.h (nonexistent) +++ src/cpu_arm_plugin/instructions.h (revision 5) @@ -0,0 +1,106 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEBUGGER_SRC_CPU_ARM_PLUGIN_INSTRUCTIONS_H__ +#define __DEBUGGER_SRC_CPU_ARM_PLUGIN_INSTRUCTIONS_H__ + +#include +#include "generic/cpu_generic.h" + +namespace debugger { + +class CpuCortex_Functional; + +class ArmInstruction : public GenericInstruction { + public: + ArmInstruction(CpuCortex_Functional *icpu, const char *name, + const char *bits); + + // IInstruction interface: + virtual const char *name() { return name_.to_string(); } + virtual int exec(Reg64Type *payload); + + /** conditions return true */ + virtual int exec_checked(Reg64Type *payload) = 0; + + + virtual bool parse(uint32_t *payload) { + return ((payload[0] & mask_) == opcode_); + } + + virtual uint32_t hash() { + return (opcode_ >> 24) & 0xF; + } + + virtual bool check_cond(uint32_t cond); + + virtual uint32_t shift12(DataProcessingType::reg_bits_type instr, + uint32_t reg, uint64_t Rs); + + virtual uint32_t imm12(DataProcessingType::imm_bits_type instr); + + protected: + virtual IFace *getInterface(const char *name); + + protected: + AttributeType name_; + CpuCortex_Functional *icpu_; + Axi4TransactionType trans_; + uint32_t mask_; + uint32_t opcode_; + uint64_t *R; +}; + +/** opcodes: + 0000 = AND - Rd:= Op1 AND Op2 + 0001 = EOR - Rd:= Op1 EOR Op2 + 0010 = SUB - Rd:= Op1 - Op2 + 0011 = RSB - Rd:= Op2 - Op1 + 0100 = ADD - Rd:= Op1 + Op2 + 0101 = ADC - Rd:= Op1 + Op2 + C + 0110 = SBC - Rd:= Op1 - Op2 + C + 0111 = RSC - Rd:= Op2 - Op1 + C + 1000 = TST - set condition codes on Op1 AND Op2 + 1001 = TEQ - set condition codes on Op1 EOR Op2 + 1010 = CMP - set condition codes on Op1 - Op2 + 1011 = CMN - set condition codes on Op1 + Op2 + 1100 = ORR - Rd:= Op1 OR Op2 + 1101 = MOV - Rd:= Op2 + 1110 = BIC - Rd:= Op1 AND NOT Op2 + 1111 = MVN - Rd:= NOT Op2 +*/ +class ArmDataProcessingInstruction : public ArmInstruction { + public: + ArmDataProcessingInstruction(CpuCortex_Functional *icpu, const char *name, + const char *bits) : ArmInstruction(icpu, name, bits) {} + + virtual int exec_checked(Reg64Type *payload); + protected: + enum EOperationResult { + OP_Drop, + OP_Write + }; + + /** Return true if need to write result into Rd register */ + virtual EOperationResult do_operation(uint32_t A, uint32_t M, + uint32_t *pRes) = 0; + virtual bool is_flags_changed(DataProcessingType u); + virtual void set_flags(uint32_t A, uint32_t M, uint32_t Res); +}; + +} // namespace debugger + +#endif // __DEBUGGER_SRC_CPU_ARM_PLUGIN_INSTRUCTIONS_H__
src/cpu_arm_plugin/instructions.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/cpu_arm_plugin/plugin_init.cpp =================================================================== --- src/cpu_arm_plugin/plugin_init.cpp (nonexistent) +++ src/cpu_arm_plugin/plugin_init.cpp (revision 5) @@ -0,0 +1,27 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "cpu_arm7_func.h" +#include "srcproc/srcproc.h" + +namespace debugger { + +extern "C" void plugin_init(void) { + REGISTER_CLASS_IDX(CpuCortex_Functional, 1); + REGISTER_CLASS_IDX(ArmSourceService, 2); +} + +} // namespace debugger
src/cpu_arm_plugin/plugin_init.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/cpu_arm_plugin/srcproc/srcproc.cpp =================================================================== --- src/cpu_arm_plugin/srcproc/srcproc.cpp (nonexistent) +++ src/cpu_arm_plugin/srcproc/srcproc.cpp (revision 5) @@ -0,0 +1,663 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "../arm-isa.h" +#include "srcproc.h" +#include + +namespace debugger { + +/** Class registration in the Core */ +enum ESymbInfo { + SymbInfo_Name, + SymbInfo_Address, + SymbInfo_Total, +}; + +const char *const *RN = IREGS_NAMES; + + +ArmSourceService::ArmSourceService(const char *name) : IService(name) { + registerInterface(static_cast(this)); + + brList_.make_list(0); + symbolListSortByName_.make_list(0); + symbolListSortByAddr_.make_list(0); + registerAttribute("Endianess", &endianess_); +} + +ArmSourceService::~ArmSourceService() { +} + +void ArmSourceService::postinitService() { +} + +void ArmSourceService::addFileSymbol(const char *name, uint64_t addr, + int sz) { + AttributeType symb(Attr_List); + symb.make_list(Symbol_Total); + symb[Symbol_Name].make_string(name); + symb[Symbol_Addr].make_uint64(addr); + symb[Symbol_Size].make_int64(sz); + + symbolListSortByName_.add_to_list(&symb); + symbolListSortByName_.sort(Symbol_Name); + + symbolListSortByAddr_.add_to_list(&symb); + symbolListSortByAddr_.sort(Symbol_Addr); +} + +void ArmSourceService::addFunctionSymbol(const char *name, + uint64_t addr, int sz) { + addFileSymbol(name, addr, sz); +} + +void ArmSourceService::addDataSymbol(const char *name, uint64_t addr, + int sz) { + addFileSymbol(name, addr, sz); +} + +void ArmSourceService::clearSymbols() { + symbolListSortByName_.make_list(0); + symbolListSortByAddr_.make_list(0); +} + +void ArmSourceService::addSymbols(AttributeType *list) { + for (unsigned i = 0; i < list->size(); i++) { + AttributeType &item = (*list)[i]; + symbolListSortByName_.add_to_list(&item); + symbolListSortByAddr_.add_to_list(&item); + } + symbolListSortByName_.sort(Symbol_Name); + symbolListSortByAddr_.sort(Symbol_Addr); +} + +void ArmSourceService::addressToSymbol(uint64_t addr, AttributeType *info) { + uint64_t sadr, send; + int sz = static_cast(symbolListSortByAddr_.size()); + + info->make_list(SymbInfo_Total); + (*info)[SymbInfo_Name].make_string(""); + (*info)[SymbInfo_Address].make_uint64(0); + if (sz == 0) { + return; + } + sadr = symbolListSortByAddr_[0u][Symbol_Addr].to_uint64(); + if (addr < sadr) { + return; + } + + bool search = true; + int dist, pos = sz / 2; + dist = pos; + while (search) { + AttributeType &symb = symbolListSortByAddr_[pos]; + sadr = symb[Symbol_Addr].to_uint64(); + if (pos < static_cast(symbolListSortByAddr_.size()) - 1) { + send = symbolListSortByAddr_[pos + 1][Symbol_Addr].to_uint64(); + } else { + send = sadr + symb[Symbol_Size].to_uint64(); + } + if (sadr <= addr && addr < send) { + (*info)[SymbInfo_Name] = symb[Symbol_Name]; + (*info)[SymbInfo_Address].make_uint64(addr - sadr); + return; + } + + if (addr < sadr) { + if (dist == 0 || pos == 0) { + search = false; + } else if (dist == 1) { + dist = 0; + pos--; + } else { + int incr = dist / 2; + pos -= incr; + dist = (dist / 2) + (dist & 0x1); + if (pos < 0) { + pos = 0; + } + } + } else { + if (dist == 0 || pos == (sz - 1)) { + search = false; + } else if (dist == 1) { + dist = 0; + pos++; + } else { + int incr = dist / 2; + pos += incr; + dist = (dist / 2) + (dist & 0x1); + if (pos >= sz) { + pos = sz - 1; + } + } + } + } +} + +int ArmSourceService::symbol2Address(const char *name, uint64_t *addr) { + for (unsigned i = 0; i < symbolListSortByName_.size(); i++) { + AttributeType &item = symbolListSortByName_[i]; + if (item[Symbol_Name].is_equal(name)) { + *addr = item[Symbol_Addr].to_uint64(); + return 0; + } + } + return -1; +} + +void ArmSourceService::registerBreakpoint(uint64_t addr, uint64_t flags, + uint64_t instr) { + AttributeType item; + item.make_list(BrkList_Total); + item[BrkList_address].make_uint64(addr); + item[BrkList_flags].make_uint64(flags); + //item[BrkList_instr].make_uint64(instr); + + bool not_found = true; + for (unsigned i = 0; i < brList_.size(); i++) { + AttributeType &br = brList_[i]; + if (addr == br[BrkList_address].to_uint64()) { + not_found = false; + } + } + if (not_found) { + brList_.add_to_list(&item); + } +} + +int ArmSourceService::unregisterBreakpoint(uint64_t addr, uint64_t *flags, + uint64_t *instr) { + for (unsigned i = 0; i < brList_.size(); i++) { + AttributeType &br = brList_[i]; + if (addr == br[BrkList_address].to_uint64()) { + *flags = br[BrkList_flags].to_uint64(); + //*instr = br[BrkList_instr].to_uint64(); + brList_.remove_from_list(i); + return 0; + } + } + return 1; +} + +void ArmSourceService::getBreakpointList(AttributeType *list) { + if (!list->is_list() || list->size() != brList_.size()) { + list->make_list(brList_.size()); + } + + for (unsigned i = 0; i < brList_.size(); i++) { + AttributeType &item = (*list)[i]; + AttributeType &br = brList_[i]; + if (!item.is_list() || item.size() != 3) { + item.make_list(BrkList_Total); + } + item[BrkList_address] = br[BrkList_address]; + item[BrkList_flags] = br[BrkList_flags]; + item[BrkList_instr] = br[BrkList_instr]; + } +} + +bool ArmSourceService::isBreakpoint(uint64_t addr, AttributeType *outbr) { + for (unsigned i = 0; i < brList_.size(); i++) { + uint64_t bradr = brList_[i][BrkList_address].to_uint64(); + if (addr == bradr) { + *outbr = brList_[i]; + return true; + } + } + return false; +} + +int ArmSourceService::disasm(uint64_t pc, + uint8_t *data, + int offset, + AttributeType *mnemonic, + AttributeType *comment) { + uint32_t instr; + memcpy(&instr, &data[offset], 4); + if ((instr & 0x0FB00000) == 0x03000000) { + return parseUndefinedInstruction(pc, instr, mnemonic, comment); + } else if ((instr & 0x0F0000F0) == 0x9 + && (((instr >> 22) & 0x3F) == 0 || ((instr >> 23) & 0x1F) == 1)) { + return parseMultiply(pc, instr, mnemonic, comment); + } else if (((instr >> 4) & 0x00FFFFFF) == 0x12FFF1) { + return parseBranchExchange(pc, instr, mnemonic, comment); + } else if ((instr & 0x0F0000F0) == 0x06000070) { + // ARM V6 operation: uxtab, uxtb, uxah, uxth.. + return parseBytesExtending(pc, instr, mnemonic, comment); + } else if (((instr >> 26) & 0x3) == 0x1) { + return parseSingleDataTransfer(pc, instr, mnemonic, comment); + } else if (((instr >> 25) & 0x7) == 0x4) { + return parseBlockDataTransfer(pc, instr, mnemonic, comment); + } else if (((instr >> 24) & 0xF) == 0xE && (instr & 0x10)) { + return parseCoprocRegTransfer(pc, instr, mnemonic, comment); + } else if (((instr >> 26) & 0x3) == 0x0) { + return parseDataProcessing(pc, instr, mnemonic, comment); + } else if (((instr >> 25) & 0x7) == 0x5) { + return parseBranch(pc, instr, mnemonic, comment); + } + mnemonic->make_string("unimpl"); + comment->make_string(""); + return 4; +} + +void ArmSourceService::disasm(uint64_t pc, + AttributeType *idata, + AttributeType *asmlist) { + asmlist->make_list(0); + if (!idata->is_data()) { + return; + } + uint8_t *data = idata->data(); + + AttributeType asm_item, symb_item, info, brpoint; + asm_item.make_list(ASM_Total); + symb_item.make_list(3); + asm_item[ASM_list_type].make_int64(AsmList_disasm); + symb_item[ASM_list_type].make_int64(AsmList_symbol); + uint64_t off = 0; + Reg64Type code; + int codesz; + + while (static_cast(off) < idata->size()) { + code.val = *reinterpret_cast(&data[off]); + + addressToSymbol(pc + off, &info); + if (info[SymbInfo_Name].size() != 0 && + info[SymbInfo_Address].to_int() == 0) { + symb_item[1].make_uint64(pc + off); + symb_item[2].make_string(info[SymbInfo_Name].to_string()); + asmlist->add_to_list(&symb_item); + } + asm_item[ASM_addrline].make_uint64(pc + off); + asm_item[ASM_breakpoint].make_boolean(false); + asm_item[ASM_label].make_string(""); + + if (isBreakpoint(pc + off, &brpoint)) { + asm_item[ASM_breakpoint].make_boolean(true); + //if (!(brpoint[BrkList_flags].to_uint64() & BreakFlag_HW)) { + // code.val = brpoint[BrkList_instr].to_uint32(); + //} + } + codesz = disasm(pc + off, + code.buf, + 0, + &asm_item[ASM_mnemonic], + &asm_item[ASM_comment]); + + uint64_t swap = code.val; + if (codesz == 2) { + swap = code.buf16[0]; + } + if (endianess_.to_int() == 1) { + swap = 0; + for (int i = 0; i < codesz; i++) { + swap = (swap << 8) | code.buf[i]; + } + } + asm_item[ASM_code].make_uint64(swap); + asm_item[ASM_codesize].make_uint64(codesz); + asmlist->add_to_list(&asm_item); + off += codesz; + } +} + +int ArmSourceService::parseUndefinedInstruction(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment) { + char tstr[64]; + if (((instr >> 20) & 0xFF) == 0x34) { + uint32_t imm16 = instr & 0xFFF; + imm16 |= ((instr & 0xF0000) >> 12); + RISCV_sprintf(tstr, sizeof(tstr), "movt %s,#%04x", + IREGS_NAMES[(instr >> 12) & 0xf], imm16); + } else { + mnemonic->make_string("unimpl"); + comment->make_string(""); + } + return 4; +} + + +int ArmSourceService::parseSingleDataTransfer(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment) { + char tstr[64]; + SingleDataTransferType u; + const char *strdown[2] = {"-", ""}; + u.value = instr; + if (u.imm_bits.L) { + if (!u.imm_bits.I) { + if (u.imm_bits.rd == Reg_pc && u.imm_bits.rn == Reg_pc + && (u.imm_bits.imm & 0x1)) { + if (u.imm_bits.imm == 0x4F) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "dsb"); + } else if (u.imm_bits.imm == 0x6F) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "isb"); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "?sb"); + } + } else { + RISCV_sprintf(tstr, sizeof(tstr), "ldr %s,[%s,#%s%d]", + IREGS_NAMES[u.imm_bits.rd], + IREGS_NAMES[u.imm_bits.rn], + strdown[u.imm_bits.U], + u.imm_bits.imm + ); + } + } else { + RISCV_sprintf(tstr, sizeof(tstr), "ldr %s,[%s,%s,LSL#%d]", + IREGS_NAMES[u.reg_bits.rd], + IREGS_NAMES[u.reg_bits.rn], + IREGS_NAMES[u.reg_bits.rm], + u.reg_bits.sh_sel + ); + } + } else { + const char *instrname[2] = {"str ", "strb "}; + if (!u.imm_bits.I) { + RISCV_sprintf(tstr, sizeof(tstr), "%s %s,[%s,#%s%d]", + instrname[u.imm_bits.B], + IREGS_NAMES[u.imm_bits.rd], + IREGS_NAMES[u.imm_bits.rn], + strdown[u.imm_bits.U], + u.imm_bits.imm + ); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "%s %s,[%s,%s,LSL#%d]", + instrname[u.imm_bits.B], + IREGS_NAMES[u.reg_bits.rd], + IREGS_NAMES[u.reg_bits.rn], + IREGS_NAMES[u.reg_bits.rm], + u.reg_bits.sh_sel + ); + } + } + mnemonic->make_string(tstr); + return 4; +} + +int ArmSourceService::parseBlockDataTransfer(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment) { + BlockDataTransferType u; + const char *instrname[2] = {"stm ", "ldm "}; + const char *spname[2] = {"push ", "pop "}; + const char *sflag[2] = {"", "^"}; + char rnames[512] = ""; + char tstr[512]; + int sz = 0; + u.value = instr; + for (int i = 0; i < 16; i++) { + if ((instr & (1 << i )) == 0) { + continue; + } + if (sz) { + sz = RISCV_sprintf(&rnames[sz], sizeof(rnames) - sz, + ",%s", IREGS_NAMES[i]); + } else { + sz = RISCV_sprintf(&rnames[sz], sizeof(rnames) - sz, + "%s", IREGS_NAMES[i]); + } + } + + if (u.bits.rn == Reg_sp) { + RISCV_sprintf(tstr, sizeof(tstr), "%s {%s}%s", + spname[u.bits.L], + rnames, + sflag[u.bits.S] + ); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "%s %s,{%s}%s", + instrname[u.bits.L], + IREGS_NAMES[u.bits.rn], + rnames, + sflag[u.bits.S] + ); + } + mnemonic->make_string(tstr); + return 4; +} + + +int ArmSourceService::parseDataProcessing(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment) { + char tstr[64]; + char op2[32]; + DataProcessingType u; + u.value = instr; + const char instr_name[][16] = { + "and ", "eor ", "sub ", "rsb ", + "add ", "adc ", "sbc ", "rsc ", + "tst ", "teq ", "cmp ", "cmn ", + "orr ", "mov ", "bic ", "mvn " + + }; + const char psrname[2][16] = {"CPSR", "SPSR"}; + // N Z C V + const char flagmask[][16] = { + "", "v", "c", "cv", + "z", "zv", "zc", "zcv", + "n", "nv", "nc", "ncv", + "nz", "nzv", "nzc", "nzcv" + }; + + if (u.imm_bits.I) { + uint32_t rsh = 2*u.imm_bits.rotate; + uint32_t imm = (u.imm_bits.imm >> rsh) + | (u.imm_bits.imm << (32 - rsh)); + RISCV_sprintf(op2, sizeof(op2), "#%d", imm); + } else { + if (u.reg_bits.shift) { + RISCV_sprintf(op2, sizeof(op2), "%s{,%d}", + IREGS_NAMES[u.reg_bits.rm], + u.reg_bits.shift); + } else { + RISCV_sprintf(op2, sizeof(op2), "%s", + IREGS_NAMES[u.reg_bits.rm], + u.reg_bits.shift); + } + } + if (instr == 0xe320f000) { + RISCV_sprintf(tstr, sizeof(tstr), "nop {%d}", 0); + } else if (u.mrs_bits.b27_23 == 0x2 && u.mrs_bits.b21_20 == 0 + && u.mrs_bits.mask == 0xF && u.mrs_bits.zero12 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "mrs %s,%s", + IREGS_NAMES[u.mrs_bits.rd], + psrname[u.mrs_bits.ps]); + } else if ((u.mrs_bits.b27_23 == 0x2 || u.mrs_bits.b27_23 == 0x6) + && u.mrs_bits.b21_20 == 0x2 + && u.mrs_bits.rd == 0xf) { + RISCV_sprintf(tstr, sizeof(tstr), "msr %s_%s,%s", + psrname[u.mrs_bits.ps], + flagmask[u.mrs_bits.mask+1], + op2 + ); + } else if (u.imm_bits.opcode == 13 || u.imm_bits.opcode == 15) { + // MOV, MVN + RISCV_sprintf(tstr, sizeof(tstr), "%s %s,%s", + instr_name[u.imm_bits.opcode], + IREGS_NAMES[u.imm_bits.rd], + op2); + } else if (u.imm_bits.opcode == 8 || u.imm_bits.opcode == 9 + || u.imm_bits.opcode == 10 || u.imm_bits.opcode == 11) { + // CMP, CMN, TEQ, TST + RISCV_sprintf(tstr, sizeof(tstr), "%s %s,%s", + instr_name[u.imm_bits.opcode], + IREGS_NAMES[u.imm_bits.rn], + op2); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "%s %s,%s,%s", + instr_name[u.imm_bits.opcode], + IREGS_NAMES[u.imm_bits.rd], + IREGS_NAMES[u.imm_bits.rn], + op2); + } + mnemonic->make_string(tstr); + return 4; +} + +int ArmSourceService::parseMultiply(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment) { + char tstr[64] = "unimpl"; + instr &= 0x0FFFFFFF; + if ((instr >> 23) == 0) { + MulType u; + u.value = instr; + if (u.bits.A) { + RISCV_sprintf(tstr, sizeof(tstr), "mla %s,%s,%s,%s", + IREGS_NAMES[u.bits.rd], + IREGS_NAMES[u.bits.rm], + IREGS_NAMES[u.bits.rs], + IREGS_NAMES[u.bits.rn]); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "mul %s,%s,%s", + IREGS_NAMES[u.bits.rd], + IREGS_NAMES[u.bits.rm], + IREGS_NAMES[u.bits.rs]); + } + } else if ((instr >> 23) == 1) { + const char *str_s[2] = {"u", "s"}; + const char *str_instr[2] = {"mull ", "mlal "}; + MulLongType u; + u.value = instr; + RISCV_sprintf(tstr, sizeof(tstr), "%s%s %s,%s,%s,%s", + str_s[u.bits.S], + str_instr[u.bits.A], + IREGS_NAMES[u.bits.rdhi], + IREGS_NAMES[u.bits.rdlo], + IREGS_NAMES[u.bits.rm], + IREGS_NAMES[u.bits.rs]); + } + mnemonic->make_string(tstr); + return 4; +} + +int ArmSourceService::parseBytesExtending(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment) { + char tstr[64] = "unimpl"; + SignExtendType u; + u.value = instr; + if (u.bits.rn == 0xF) { + if (u.bits.b27_20 == 0x6E) { + RISCV_sprintf(tstr, sizeof(tstr), "uxtb %s,%s,sh#%d", + IREGS_NAMES[u.bits.rd], + IREGS_NAMES[u.bits.rm], + 8*u.bits.rotate); + } else if (u.bits.b27_20 == 0x6C) { + RISCV_sprintf(tstr, sizeof(tstr), "uxtb16 %s,%s,sh#%d", + IREGS_NAMES[u.bits.rd], + IREGS_NAMES[u.bits.rm], + 8*u.bits.rotate); + } else if (u.bits.b27_20 == 0x6F) { + RISCV_sprintf(tstr, sizeof(tstr), "uxth %s,%s,sh#%d", + IREGS_NAMES[u.bits.rd], + IREGS_NAMES[u.bits.rm], + 8*u.bits.rotate); + } + } else { + if (u.bits.b27_20 == 0x6E) { + RISCV_sprintf(tstr, sizeof(tstr), "uxtab %s,%s,%s,sh#%d", + IREGS_NAMES[u.bits.rd], + IREGS_NAMES[u.bits.rn], + IREGS_NAMES[u.bits.rm], + 8*u.bits.rotate); + } else if (u.bits.b27_20 == 0x6C) { + RISCV_sprintf(tstr, sizeof(tstr), "uxtab16 %s,%s,%s,sh#%d", + IREGS_NAMES[u.bits.rd], + IREGS_NAMES[u.bits.rn], + IREGS_NAMES[u.bits.rm], + 8*u.bits.rotate); + } else if (u.bits.b27_20 == 0x6F) { + RISCV_sprintf(tstr, sizeof(tstr), "uxtah %s,%s,%s,sh#%d", + IREGS_NAMES[u.bits.rd], + IREGS_NAMES[u.bits.rn], + IREGS_NAMES[u.bits.rm], + 8*u.bits.rotate); + } + } + mnemonic->make_string(tstr); + return 4; +} + + +int ArmSourceService::parseCoprocRegTransfer(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment) { + char tstr[64] = "unimpl"; + CoprocessorTransferType u; + u.value = instr; + const char instr_name[2][16] = {"mcr ", "mrc "}; + RISCV_sprintf(tstr, sizeof(tstr), "%s p%d,%d,%s,c%d,c%d,%d", + instr_name[u.bits.L], + u.bits.cp_num, + u.bits.mode, + IREGS_NAMES[u.bits.rd], + u.bits.crn, + u.bits.crm, + u.bits.cp_nfo + ); + mnemonic->make_string(tstr); + return 4; +} + +int ArmSourceService::parseBranch(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment) { + char tstr[64]; + BranchType u; + u.value = instr; + const char *flags[16] = { + "eq", "ne", "cs", "cc", "mi", "pl", "vs", "vc", + "hi", "ls", "ge", "lt", "gt", "le", "", "" + }; + + uint32_t off = u.bits.offset; + if ((u.value >> 23) & 0x1) { + off |= 0xFF000000; + } + off = static_cast(pc + (off << 2) + 8); + + if (u.bits.L) { + RISCV_sprintf(tstr, sizeof(tstr), "bl %x", + off); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "b%2s %x", + flags[u.bits.cond], + off); + } + mnemonic->make_string(tstr); + return 4; +} + +int ArmSourceService::parseBranchExchange(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment) { + char tstr[64]; + BranchType u; + u.value = instr; + + RISCV_sprintf(tstr, sizeof(tstr), "bx %s", + IREGS_NAMES[u.bits.offset & 0xF]); + mnemonic->make_string(tstr); + return 4; +} + +} // namespace debugger
src/cpu_arm_plugin/srcproc/srcproc.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/cpu_arm_plugin/srcproc/srcproc.h =================================================================== --- src/cpu_arm_plugin/srcproc/srcproc.h (nonexistent) +++ src/cpu_arm_plugin/srcproc/srcproc.h (revision 5) @@ -0,0 +1,113 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEBUGGER_SRCPROC_H__ +#define __DEBUGGER_SRCPROC_H__ + +#include +#include +#include "coreservices/isrccode.h" + +namespace debugger { + +class ArmSourceService : public IService, + public ISourceCode { + public: + explicit ArmSourceService(const char *name); + virtual ~ArmSourceService(); + + /** IService interface */ + virtual void postinitService(); + + /** ISourceCode interface */ + virtual void addFileSymbol(const char *name, uint64_t addr, int sz); + + virtual void addFunctionSymbol(const char *name, uint64_t addr, int sz); + + virtual void addDataSymbol(const char *name, uint64_t addr, int sz); + + virtual void addSymbols(AttributeType *list); + + virtual void clearSymbols(); + + virtual void getSymbols(AttributeType *list) { + *list = symbolListSortByName_; + } + + virtual void addressToSymbol(uint64_t addr, AttributeType *info); + + virtual int symbol2Address(const char *name, uint64_t *addr); + + virtual int disasm(uint64_t pc, + uint8_t *data, + int offset, + AttributeType *mnemonic, + AttributeType *comment); + virtual void disasm(uint64_t pc, + AttributeType *idata, + AttributeType *asmlist); + + virtual void registerBreakpoint(uint64_t addr, uint64_t flags, + uint64_t instr); + + virtual int unregisterBreakpoint(uint64_t addr, uint64_t *flags, + uint64_t *instr); + + virtual void getBreakpointList(AttributeType *list); + + virtual bool isBreakpoint(uint64_t addr, AttributeType *outbr); + + private: + int parseUndefinedInstruction(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment); + int parseSingleDataTransfer(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment); + int parseBlockDataTransfer(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment); + int parseDataProcessing(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment); + int parseMultiply(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment); + int parseBytesExtending(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment); + int parseCoprocRegTransfer(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment); + int parseBranch(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment); + int parseBranchExchange(uint64_t pc, uint32_t instr, + AttributeType *mnemonic, + AttributeType *comment); + + private: + AttributeType endianess_; + AttributeType brList_; + AttributeType symbolListSortByName_; + AttributeType symbolListSortByAddr_; +}; + +DECLARE_CLASS(ArmSourceService) + +} // namespace debugger + +#endif // __DEBUGGER_SRCPROC_H__
src/cpu_arm_plugin/srcproc/srcproc.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/cpu_fnc_plugin/riscv-ext-c.cpp =================================================================== --- src/cpu_fnc_plugin/riscv-ext-c.cpp (nonexistent) +++ src/cpu_fnc_plugin/riscv-ext-c.cpp (revision 5) @@ -0,0 +1,1023 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief RISC-V extension-C (Comporessed Instructions). + */ + +#include "api_utils.h" +#include "riscv-isa.h" +#include "cpu_riscv_func.h" + +namespace debugger { + +/** + * @brief Add register to register + * + * C.ADD adds the values in registers rd and rs2 and writes the result to + * register rd. C.ADD expands into add rd, rd, rs2. + */ +class C_ADD : public RiscvInstruction16 { +public: + C_ADD(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_ADD", "????????????????1001??????????10") {} + + virtual bool parse(uint32_t *payload) { + ISA_CR_type u; + u.value = static_cast(payload[0]); + return RiscvInstruction::parse(payload) + && u.bits.rdrs1 && u.bits.rs2; + } + + virtual int exec(Reg64Type *payload) { + ISA_CR_type u; + u.value = payload->buf16[0]; + if (u.bits.rdrs1) { + R[u.bits.rdrs1] += R[u.bits.rs2]; + } + return 2; + } +}; + +/** + * @brief Add immediate + * + * C.ADDI adds the non-zero sign-extended 6-bit immediate to the value in + * register rd then writes the result to rd. C.ADDI expands into + * addi rd, rd, nzimm[5:0]. + */ +class C_ADDI : public RiscvInstruction16 { +public: + C_ADDI(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_ADDI", "????????????????000???????????01") {} + + virtual bool parse(uint32_t *payload) { + ISA_CR_type u; + u.value = static_cast(payload[0]); + return RiscvInstruction::parse(payload) && u.bits.rdrs1; + } + + virtual int exec(Reg64Type *payload) { + ISA_CI_type u; + u.value = payload->buf16[0]; + + uint64_t imm = u.bits.imm; + if (u.bits.imm6) { + imm |= EXT_SIGN_6; + } + R[u.bits.rdrs] = R[u.bits.rdrs] + imm; + return 2; + } +}; + +/** + * @brief Stack-relative Add immediate + * + * C.ADDI16SP shares the opcode with C.LUI, but has a destination field of x2. + * C.ADDI16SP adds the non-zero sign-extended 6-bit immediate to the value in + * the stack pointer (sp=x2), where the immediate is scaled to represent + * multiples of 16 in the range (-512,496). C.ADDI16SP is used to adjust the + * stack pointer in procedure prologues and epilogues. It expands into + * addi x2, x2, nzimm[9:4]. + */ +class C_ADDI16SP : public RiscvInstruction16 { +public: + C_ADDI16SP(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_ADDI16SP", "????????????????011?00010?????01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CI_type u; + u.value = payload->buf16[0]; + + uint64_t imm = (u.spbits.imm8_7 << 3) | (u.spbits.imm6 << 2) + | (u.spbits.imm5 << 1) | u.spbits.imm4; + if (u.spbits.imm9) { + imm |= EXT_SIGN_6; + } + imm <<= 4; + R[Reg_sp] = R[Reg_sp] + imm; + return 2; + } +}; + +/** + * @brief Stack-relative Add wide immediate + * + * C.ADDI4SPN is a CIW-format RV32C/RV64C-only instruction that adds a + * zero-extended non-zero immediate, scaled by 4, to the stack pointer, x2, + * and writes the result to rd0. This instruction is used to generate + * pointers to stack-allocated variables, and expands to + * addi rd0, x2, zimm[9:2]. + */ +class C_ADDI4SPN : public RiscvInstruction16 { +public: + C_ADDI4SPN(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_ADDI4SPN", "????????????????000???????????00") {} + + virtual int exec(Reg64Type *payload) { + ISA_CIW_type u; + u.value = payload->buf16[0]; + + uint64_t imm = (u.bits.imm9_6 << 4) | (u.bits.imm5_4 << 2) + | (u.bits.imm3 << 1) | u.bits.imm2; + imm <<= 2; + R[8 + u.bits.rd] = R[Reg_sp] + imm; + return 2; + } +}; + +/** + * @brief Add immediate with sign extending + * + * C.ADDIW is an RV64C/RV128C-only instruction that performs the same + * computation but produces a 32-bit result, then sign-extends result + * to 64 bits. C.ADDIW expands into addiw rd, rd, imm[5:0]. The immediate + * can be zero for C.ADDIW, where this corresponds to sext.w rd. + */ +class C_ADDIW : public RiscvInstruction16 { +public: + C_ADDIW(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_ADDIW", "????????????????001???????????01") {} + + virtual bool parse(uint32_t *payload) { + ISA_CR_type u; + u.value = static_cast(payload[0]); + return RiscvInstruction::parse(payload) && u.bits.rdrs1; + } + + virtual int exec(Reg64Type *payload) { + ISA_CI_type u; + u.value = payload->buf16[0]; + + uint64_t imm = u.bits.imm; + if (u.bits.imm6) { + imm |= EXT_SIGN_6; + } + R[u.bits.rdrs] = (R[u.bits.rdrs] + imm) & 0xFFFFFFFFLL; + if (R[u.bits.rdrs] & (1LL << 31)) { + R[u.bits.rdrs] |= EXT_SIGN_32; + } + return 2; + } +}; + +/** + * @brief C_ADDW + * + * C.ADDW is an RV64C/RV128C-only instruction that adds the values in registers + * rd' and rs2', then sign-extends the lower 32 bits of the sum before writing + * the result to register rd'. C.ADDW expands into addw rd', rd', rs2'. + */ +class C_ADDW : public RiscvInstruction16 { +public: + C_ADDW(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_ADDW", "????????????????100111???01???01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CS_type u; + u.value = payload->buf16[0]; + R[8 + u.bits.rs1] += R[8 + u.bits.rs2]; + R[8 + u.bits.rs1] &= 0xFFFFFFFFLL; + + if (R[8 + u.bits.rs1] & (1LL << 31)) { + R[8 + u.bits.rs1] |= EXT_SIGN_32; + } + return 2; + } +}; + + +/** + * @brief C_AND + * + * C.AND computes the bitwise AND of the values in registers rd' and rs2', then + * writes the result to register rd'. C.AND expands into and rd', rd', rs2'. + */ +class C_AND : public RiscvInstruction16 { +public: + C_AND(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_AND", "????????????????100011???11???01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CS_type u; + u.value = payload->buf16[0]; + R[8 + u.bits.rs1] &= R[8 + u.bits.rs2]; + return 2; + } +}; + +/** + * @brief AND with sign-extended immediate + * + * C.ANDI is a CB-format instruction that computes the bitwise AND of the + * value in register rd' and the sign-extended 6-bit immediate, then writes + * the result to rd'. C.ANDI expands to andi rd', rd', imm[5:0]. + */ +class C_ANDI : public RiscvInstruction16 { +public: + C_ANDI(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_ANDI", "????????????????100?10????????01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CB_type u; + u.value = payload->buf16[0]; + + uint64_t imm = (u.bits.off7_6 << 3) | (u.bits.off2_1 << 1) | u.bits.off5; + if (u.bits.off8) { + imm |= EXT_SIGN_5; + } + R[8 + u.bits.rs1] &= imm; + return 2; + } +}; + +/** + * @brief Branch if registers zero + * + * C.BEQZ performs conditional control transfers. The offset is sign-extended + * and added to the pc to form the branch target address. It can therefore + * target a 256B range. C.BEQZ takes the branch if the value in register rs1' + * is zero. It expands to beq rs1', x0, offset[8:1]. + */ +class C_BEQZ : public RiscvInstruction16 { +public: + C_BEQZ(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_BEQZ", "????????????????110???????????01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CB_type u; + u.value = payload->buf32[0]; + + if (R[8 + u.bits.rs1] == 0) { + uint64_t imm = (u.bits.off7_6 << 5) | (u.bits.off5 << 4) + | (u.bits.off4_3 << 2) | u.bits.off2_1; + imm <<= 1; + if (u.bits.off8) { + imm |= EXT_SIGN_9; + } + icpu_->setBranch(icpu_->getPC() + imm); + } + return 2; + } +}; + + +/** + * @brief Branch if registers not zero + * + * C.BNEZ is defined analogously, but it takes the branch if rs1' contains a + * nonzero value. It expands to bne rs1', x0, offset[8:1]. + */ +class C_BNEZ : public RiscvInstruction16 { +public: + C_BNEZ(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_BNEZ", "????????????????111???????????01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CB_type u; + u.value = payload->buf32[0]; + + if (R[8 + u.bits.rs1]) { + uint64_t imm = (u.bits.off7_6 << 5) | (u.bits.off5 << 4) + | (u.bits.off4_3 << 2) | u.bits.off2_1; + imm <<= 1; + if (u.bits.off8) { + imm |= EXT_SIGN_9; + } + icpu_->setBranch(icpu_->getPC() + imm); + } + return 2; + } +}; + +/** + * @brief C.EBREAK (breakpoint instruction) + * + * The C.EBREAK instruction is used by debuggers to cause control to be + * transferred back to a debug-ging environment. + */ +class C_EBREAK : public RiscvInstruction16 { +public: + C_EBREAK(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_EBREAK", "????????????????1001000000000010") {} + + virtual int exec(Reg64Type *payload) { + icpu_->raiseSignal(EXCEPTION_Breakpoint); + return 2; + } +}; + + +/** + * @brief Unconditional jump + * + * C.J performs an unconditional control transfer. The offset is sign-extended + * and added to the pc to form the jump target address. C.J can therefore + * target a 2 KiB range. C.J expands to jal x0, offset[11:1]. + */ +class C_J : public RiscvInstruction16 { +public: + C_J(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_J", "????????????????101???????????01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CJ_type u; + u.value = payload->buf16[0]; + uint64_t off = (u.bits.off10 << 9) | (u.bits.off9_8 << 7) + | (u.bits.off7 << 6) | (u.bits.off6 << 5) + | (u.bits.off5 << 4) | (u.bits.off4 << 3) + | u.bits.off3_1; + off <<= 1; + if (u.bits.off11) { + off |= EXT_SIGN_11; + } + icpu_->setBranch(icpu_->getPC() + off); + return 2; + } +}; + +#ifdef RV32C_ONLY // conflict with C_ADDIW +/** + * @brief Unconditional jump with write to ra + * + * C.JAL is an RV32C-only instruction that performs the same operation as C.J, + * but additionally writes the address of the instruction following the jump + * (pc+2) to the link register, x1. C.JAL expands to jal x1, offset[11:1]. + */ +class C_JAL : public RiscvInstruction16 { +public: + C_JAL(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_JAL", "????????????????001???????????01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CJ_type u; + u.value = payload->buf16[0]; + uint64_t off = (u.bits.off10 << 9) | (u.bits.off9_8 << 7) + | (u.bits.off7 << 6) | (u.bits.off6 << 5) + | (u.bits.off5 << 4) | (u.bits.off4 << 3) + | u.bits.off3_1; + off <<= 1; + if (u.bits.off11) { + off |= EXT_SIGN_11; + } + R[Reg_ra] = icpu_->getPC() + 2; + icpu_->setBranch(icpu_->getPC() + off); + icpu_->pushStackTrace(); + return 2; + } +}; +#endif + +/** + * @brief Unconditional jump with write to ra + * + * C.JALR (jump and link register) performs the same operation as C.JR, but + * additionally writes the address of the instruction following the jump (pc+2) + * to the link register, x1. C.JALR expands to jalr x1, rs1, 0. + */ +class C_JALR : public RiscvInstruction16 { +public: + C_JALR(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_JALR", "????????????????1001?????0000010") {} + + virtual bool parse(uint32_t *payload) { + ISA_CR_type u; + u.value = static_cast(payload[0]); + return RiscvInstruction::parse(payload) && u.bits.rdrs1; + } + + virtual int exec(Reg64Type *payload) { + ISA_CR_type u; + u.value = payload->buf16[0]; + R[Reg_ra] = icpu_->getPC() + 2; + icpu_->setBranch(R[u.bits.rdrs1]); + icpu_->pushStackTrace(); + return 2; + } +}; + +/** + * @brief Unconditional jump + * + * C.JR (jump register) performs an unconditional control transfer to the + * address in register rs1. C.JR expands to jalr x0, rs1, 0. + */ +class C_JR : public RiscvInstruction16 { +public: + C_JR(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_JR", "????????????????1000?????0000010") {} + + virtual bool parse(uint32_t *payload) { + ISA_CR_type u; + u.value = static_cast(payload[0]); + return RiscvInstruction::parse(payload) && u.bits.rdrs1; + } + + virtual int exec(Reg64Type *payload) { + ISA_CR_type u; + u.value = payload->buf16[0]; + icpu_->setBranch(R[u.bits.rdrs1]); + if (u.bits.rdrs1 == Reg_ra) { + icpu_->popStackTrace(); + } + return 2; + } +}; + +/** + * @brief LOAD instructions with sign extending. + * + * C.LD is an RV64C/RV128C-only instruction that loads a 64-bit value from + * memory into register rd0. It computes an e ective address by adding the + * zero-extended o set, scaled by 8, to the base address in register rs10. + * It expands to ld rd0, offset[7:3](rs10). + */ +class C_LD : public RiscvInstruction16 { +public: + C_LD(CpuRiver_Functional *icpu) : + RiscvInstruction16(icpu, "C_LD", "????????????????011???????????00") {} + + virtual int exec(Reg64Type *payload) { + Axi4TransactionType trans; + ISA_CL_type u; + u.value = payload->buf16[0]; + uint64_t off = (u.bits.imm27 << 4) | (u.bits.imm6 << 3) + | u.bits.imm5_3; + off <<= 3; + trans.action = MemAction_Read; + trans.addr = R[8 + u.bits.rs1] + off; + trans.xsize = 8; + if (trans.addr & 0x7) { + trans.rpayload.b64[0] = 0; + icpu_->raiseSignal(EXCEPTION_LoadMisalign); + } else { + icpu_->dma_memop(&trans); + } + R[8 + u.bits.rd] = trans.rpayload.b64[0]; + return 2; + } +}; + +/** + * @brief LOAD stack-relative dword. + * + * C.LDSP is an RV64C/RV128C-only instruction that loads a 64-bit value from + * memory into register rd. It computes its e ective address by adding the + * zero-extended o set, scaled by 8, to the stack pointer, x2. + * It expands to ld rd, offset[8:3](x2). + */ +class C_LDSP : public RiscvInstruction16 { +public: + C_LDSP(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_LDSP", "????????????????011???????????10") {} + + virtual bool parse(uint32_t *payload) { + ISA_CR_type u; + u.value = static_cast(payload[0]); + return RiscvInstruction::parse(payload) && u.bits.rdrs1; + } + + virtual int exec(Reg64Type *payload) { + Axi4TransactionType trans; + ISA_CI_type u; + u.value = payload->buf16[0]; + uint64_t off = (u.ldspbits.off8_6 << 3) | (u.ldspbits.off5 << 2) + | u.ldspbits.off4_3; + off <<= 3; + trans.action = MemAction_Read; + trans.addr = R[Reg_sp] + off; + trans.xsize = 8; + if (trans.addr & 0x7) { + trans.rpayload.b64[0] = 0; + icpu_->raiseSignal(EXCEPTION_LoadMisalign); + } else { + icpu_->dma_memop(&trans); + } + R[u.ldspbits.rd] = trans.rpayload.b64[0]; + return 2; + } +}; + +/** + * @brief Constant generation + * + * C.LI loads the sign-extended 6-bit immediate, imm, into register rd. C.LI is + * only valid when rd /= x0. C.LI expands into addi rd, x0, imm[5:0]. + */ +class C_LI : public RiscvInstruction16 { +public: + C_LI(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_LI", "????????????????010???????????01") {} + + virtual bool parse(uint32_t *payload) { + ISA_CR_type u; + u.value = static_cast(payload[0]); + return RiscvInstruction::parse(payload) && u.bits.rdrs1; + } + + virtual int exec(Reg64Type *payload) { + ISA_CI_type u; + u.value = payload->buf16[0]; + + uint64_t imm = u.bits.imm; + if (u.bits.imm6) { + imm |= EXT_SIGN_6; + } + R[u.bits.rdrs] = imm; + return 2; + } +}; + +/** + * @brief LOAD instructions with sign extending. + * + * C.LW loads a 32-bit value from memory into register rd0. It computes an + * effective address by adding the zero-extended offset, scaled by 4, to the + * base address in register rs10. It expands to lw rd0, offset[6:2](rs10). + */ +class C_LW : public RiscvInstruction16 { +public: + C_LW(CpuRiver_Functional *icpu) : + RiscvInstruction16(icpu, "C_LW", "????????????????010???????????00") {} + + virtual int exec(Reg64Type *payload) { + Axi4TransactionType trans; + ISA_CL_type u; + u.value = payload->buf16[0]; + uint64_t off = (u.bits.imm6 << 4) | (u.bits.imm5_3 << 1) | u.bits.imm27; + off <<= 2; + trans.action = MemAction_Read; + trans.addr = R[8 + u.bits.rs1] + off; + trans.xsize = 4; + trans.rpayload.b64[0] = 0; + if (trans.addr & 0x3) { + trans.rpayload.b64[0] = 0; + icpu_->raiseSignal(EXCEPTION_LoadMisalign); + } else { + icpu_->dma_memop(&trans); + } + R[8 + u.bits.rd] = trans.rpayload.b32[0]; + if (R[8 + u.bits.rd] & (1LL << 31)) { + R[8 + u.bits.rd] |= EXT_SIGN_32; + } + return 2; + } +}; + +/** + * @brief LOAD stack-relative word. + * + * C.LWSP loads a 32-bit value from memory into register rd. It computes + * an e ective address by adding the zero-extended o set, scaled by 4, to the + * stack pointer, x2. It expands to lw rd, offset[7:2](x2). + */ +class C_LWSP : public RiscvInstruction16 { +public: + C_LWSP(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_LWSP", "????????????????010???????????10") {} + + virtual bool parse(uint32_t *payload) { + ISA_CR_type u; + u.value = static_cast(payload[0]); + return RiscvInstruction::parse(payload) && u.bits.rdrs1; + } + + virtual int exec(Reg64Type *payload) { + Axi4TransactionType trans; + ISA_CI_type u; + u.value = payload->buf16[0]; + uint64_t off = (u.lwspbits.off7_6 << 4) | (u.lwspbits.off5 << 3) + | u.lwspbits.off4_2; + off <<= 2; + trans.action = MemAction_Read; + trans.addr = R[Reg_sp] + off; + trans.xsize = 4; + if (trans.addr & 0x3) { + trans.rpayload.b64[0] = 0; + icpu_->raiseSignal(EXCEPTION_LoadMisalign); + } else { + icpu_->dma_memop(&trans); + } + R[u.lwspbits.rd] = trans.rpayload.b32[0]; + if (R[u.lwspbits.rd] & (1LL << 31)) { + R[u.lwspbits.rd] |= EXT_SIGN_32; + } + return 2; + } +}; + +/** + * @brief Constant generation + * + * C.LUI loads the non-zero 6-bit immediate eld into bits 17-12 of the + * destination register, clears the bottom 12 bits, and sign-extends + * bit 17 into all higher bits of the destination. C.LUI is only + * valid when rd /= {x0; x2}, and when the immediate is not equal to zero. + * C.LUI expands into lui rd, nzuimm[17:12]. + */ +class C_LUI : public RiscvInstruction16 { +public: + C_LUI(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_LUI", "????????????????011???????????01") {} + + virtual bool parse(uint32_t *payload) { + ISA_CR_type u; + u.value = static_cast(payload[0]); + return RiscvInstruction::parse(payload) && u.bits.rdrs1 + && u.bits.rdrs1 != Reg_sp; + } + + virtual int exec(Reg64Type *payload) { + ISA_CI_type u; + u.value = payload->buf16[0]; + + uint64_t imm = u.bits.imm; + if (u.bits.imm6) { + imm |= EXT_SIGN_6; + } + imm <<= 12; + R[u.bits.rdrs] = imm; + return 2; + } +}; + +/** + * @brief Move register to register + * + * C.MV copies the value in register rs2 into register rd. C.MV expands + * into add rd, x0, rs2. + */ +class C_MV : public RiscvInstruction16 { +public: + C_MV(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_MV", "????????????????1000??????????10") {} + + virtual bool parse(uint32_t *payload) { + ISA_CR_type u; + u.value = static_cast(payload[0]); + return RiscvInstruction::parse(payload) + && u.bits.rs2 && u.bits.rdrs1; + } + + virtual int exec(Reg64Type *payload) { + ISA_CR_type u; + u.value = payload->buf16[0]; + R[u.bits.rdrs1] = R[u.bits.rs2]; + return 2; + } +}; + +/** + * @brief empty cycle + */ +class C_NOP : public RiscvInstruction16 { +public: + C_NOP(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_NOP", "????????????????0000000000000001") {} + + virtual bool parse(uint32_t *payload) { + return RiscvInstruction::parse(payload); + } + + virtual int exec(Reg64Type *payload) { + return 2; + } +}; + + +/** + * @brief C_OR + * + * C.OR computes the bitwise OR of the values in registers rd' and rs2', then + * writes the result to register rd'. C.OR expands into or rd', rd', rs2'. + */ +class C_OR : public RiscvInstruction16 { +public: + C_OR(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_OR", "????????????????100011???10???01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CS_type u; + u.value = payload->buf16[0]; + R[8 + u.bits.rs1] |= R[8 + u.bits.rs2]; + return 2; + } +}; + +/** + * @brief Store 64-bits data + * + * C.SD is an RV64C/RV128C-only instruction that stores a 64-bit value in + * register rs20 to memory. It computes an e ective address by adding the + * zero-extended o set, scaled by 8, to the base address in register rs10. It + * expands to sd rs20, offset[7:3](rs10). + */ +class C_SD : public RiscvInstruction16 { +public: + C_SD(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_SD", "????????????????111???????????00") {} + + virtual int exec(Reg64Type *payload) { + Axi4TransactionType trans; + ISA_CS_type u; + u.value = payload->buf16[0]; + uint64_t off = (u.bits.imm27 << 4) | (u.bits.imm6 << 3) | u.bits.imm5_3; + off <<= 3; + trans.action = MemAction_Write; + trans.xsize = 8; + trans.wstrb = (1 << trans.xsize) - 1; + trans.addr = R[8 + u.bits.rs1] + off; + trans.wpayload.b64[0] = R[8 + u.bits.rs2]; + if (trans.addr & 0x7) { + icpu_->raiseSignal(EXCEPTION_StoreMisalign); + } else { + icpu_->dma_memop(&trans); + } + return 2; + } +}; + +/** + * @brief Stack-relative Store 64-bits data + * + * C.SDSP is an RV64C/RV128C-only instruction that stores a 64-bit value + * in register rs2 to memory. It computes an e ective address by adding the + * zero-extended o set, scaled by 8, to the stack pointer, x2. It expands + * to sd rs2, offset[8:3](x2). + */ +class C_SDSP : public RiscvInstruction16 { +public: + C_SDSP(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_SDSP", "????????????????111???????????10") {} + + virtual int exec(Reg64Type *payload) { + Axi4TransactionType trans; + ISA_CSS_type u; + u.value = payload->buf16[0]; + uint64_t off = (u.dbits.imm8_6 << 3) | u.dbits.imm5_3; + off <<= 3; + trans.action = MemAction_Write; + trans.xsize = 8; + trans.wstrb = (1 << trans.xsize) - 1; + trans.addr = R[Reg_sp] + off; + trans.wpayload.b64[0] = R[u.dbits.rs2]; + if (trans.addr & 0x7) { + icpu_->raiseSignal(EXCEPTION_StoreMisalign); + } else { + icpu_->dma_memop(&trans); + } + return 2; + } +}; + +/** + * @brief Logical shift left + * + * C.SLLI is a CI-format instruction that performs a logical left shift + * of the value in register rd then writes the result to rd. The shift amount + * is encoded in the shamt eld, where shamt[5] must be zero for RV32C. + * For RV32C and RV64C, the shift amount must be non-zero. For RV128C, a shift + * amount of zero is used to encode a shift of 64. C.SLLI expands into + * slli rd, rd, shamt[5:0], except for RV128C with shamt=0, which expands + * to slli rd, rd, 64. + */ +class C_SLLI : public RiscvInstruction16 { +public: + C_SLLI(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_SLLI", "????????????????000???????????10") {} + + virtual bool parse(uint32_t *payload) { + ISA_CR_type u; + u.value = static_cast(payload[0]); + return RiscvInstruction::parse(payload) && u.bits.rdrs1; + } + + virtual int exec(Reg64Type *payload) { + ISA_CB_type u; + u.value = payload->buf16[0]; + uint32_t shamt = (u.shbits.shamt5 << 5) | u.shbits.shamt; + uint32_t idx = (u.shbits.funct2 << 3) | u.shbits.rd; + R[idx] = R[idx] << shamt; + return 2; + } +}; + +/** + * @brief Arith shift right + * + * C.SRAI is defined analogously to C.SRLI, but instead performs an arithmetic + * right shift. C.SRAI expands to srai rd', rd', shamt[5:0]. + */ +class C_SRAI : public RiscvInstruction16 { +public: + C_SRAI(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_SRAI", "????????????????100?01????????01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CB_type u; + u.value = payload->buf16[0]; + uint32_t shamt = (u.shbits.shamt5 << 5) | u.shbits.shamt; + R[8 + u.shbits.rd] = static_cast(R[8 + u.shbits.rd]) >> shamt; + return 2; + } +}; + +/** + * @brief Logical shift right + * + * C.SRLI is a CB-format instruction that performs a logical right shift of + * the value in register rd' then writes the result to rd'. The shift amount + * is encoded in the shamt field, where shamt[5] must be zero for RV32C. + * For RV32C and RV64C, the shift amount must be non-zero. For RV128C, a shift + * amount of zero is used to encode a shift of 64. Furthermore, the shift + * amount is sign-extended for RV128C, and so the legal shift amounts are + * 1-31, 64, and 96-127. C.SRLI expands into srli rd0, rd0, shamt[5:0], + * except for RV128C with shamt=0, which expands to srli rd0, rd0, 64. + */ +class C_SRLI : public RiscvInstruction16 { +public: + C_SRLI(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_SRLI", "????????????????100?00????????01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CB_type u; + u.value = payload->buf16[0]; + uint32_t shamt = (u.shbits.shamt5 << 5) | u.shbits.shamt; + R[8 + u.shbits.rd] = R[8 + u.shbits.rd] >> shamt; + return 2; + } +}; + +/** + * @brief C_SUB + * + * C.SUB subtracts the value in register rs2' from the value in register rd', + * then writes the result to register rd'. C.SUB expands into + * sub rd', rd', rs2'. + */ +class C_SUB : public RiscvInstruction16 { +public: + C_SUB(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_SUB", "????????????????100011???00???01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CS_type u; + u.value = payload->buf16[0]; + R[8 + u.bits.rs1] -= R[8 + u.bits.rs2]; + return 2; + } +}; + +/** + * @brief C_SUBW + * + * C.SUBW is an RV64C/RV128C-only instruction that subtracts the value in + * register rs2' from the value in register rd', then sign-extends the lower + * 32 bits of the difference before writing the result to register rd'. + * C.SUBW expands into subw rd', rd', rs2'. + */ +class C_SUBW : public RiscvInstruction16 { +public: + C_SUBW(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_SUBW", "????????????????100111???00???01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CS_type u; + u.value = payload->buf16[0]; + R[8 + u.bits.rs1] -= R[8 + u.bits.rs2]; + R[8 + u.bits.rs1] &= 0xFFFFFFFFLL; + + if (R[8 + u.bits.rs1] & (1LL << 31)) { + R[8 + u.bits.rs1] |= EXT_SIGN_32; + } + return 2; + } +}; + +/** + * @brief Store word + * + * C.SW stores a 32-bit value in register rs20 to memory. It computes an + * effective address by adding the zero-extended o set, scaled by 4, to the + * base address in register rs10. It expands to sw rs20, offset[6:2](rs10). + */ +class C_SW : public RiscvInstruction16 { +public: + C_SW(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_SW", "????????????????110???????????00") {} + + virtual int exec(Reg64Type *payload) { + Axi4TransactionType trans; + ISA_CS_type u; + u.value = payload->buf16[0]; + uint64_t off = (u.bits.imm6 << 4) | (u.bits.imm5_3 << 1) | u.bits.imm27; + off <<= 2; + trans.action = MemAction_Write; + trans.xsize = 4; + trans.wstrb = (1 << trans.xsize) - 1; + trans.addr = R[8 + u.bits.rs1] + off; + trans.wpayload.b64[0] = R[8 + u.bits.rs2]; + if (trans.addr & 0x3) { + icpu_->raiseSignal(EXCEPTION_StoreMisalign); + } else { + icpu_->dma_memop(&trans); + } + return 2; + } +}; + +/** + * @brief Stack-relative Store word + * + * C.SWSP stores a 32-bit value in register rs2 to memory. It computes an + * effective address by adding the zero-extended o set, scaled by 4, to the + * stack pointer, x2. It expands to sw rs2, offset[7:2](x2). + */ +class C_SWSP : public RiscvInstruction16 { +public: + C_SWSP(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_SWSP", "????????????????110???????????10") {} + + virtual int exec(Reg64Type *payload) { + Axi4TransactionType trans; + ISA_CSS_type u; + u.value = payload->buf16[0]; + uint64_t off = (u.wbits.imm7_6 << 4) | u.wbits.imm5_2; + off <<= 2; + trans.action = MemAction_Write; + trans.xsize = 4; + trans.wstrb = (1 << trans.xsize) - 1; + trans.addr = R[Reg_sp] + off; + trans.wpayload.b64[0] = R[u.wbits.rs2]; + if (trans.addr & 0x3) { + icpu_->raiseSignal(EXCEPTION_StoreMisalign); + } else { + icpu_->dma_memop(&trans); + } + return 2; + } +}; + +/** + * @brief C_XOR + * + * C.XOR computes the bitwise XOR of the values in registers rd' and rs2', then + * writes the result to register rd'. C.XOR expands into xor rd', rd', rs2'. + */ +class C_XOR : public RiscvInstruction16 { +public: + C_XOR(CpuRiver_Functional *icpu) : RiscvInstruction16(icpu, + "C_XOR", "????????????????100011???01???01") {} + + virtual int exec(Reg64Type *payload) { + ISA_CS_type u; + u.value = payload->buf16[0]; + R[8 + u.bits.rs1] ^= R[8 + u.bits.rs2]; + return 2; + } +}; + + +void CpuRiver_Functional::addIsaExtensionC() { + addSupportedInstruction(new C_ADD(this)); + addSupportedInstruction(new C_ADDI(this)); + addSupportedInstruction(new C_ADDI16SP(this)); + addSupportedInstruction(new C_ADDI4SPN(this)); + addSupportedInstruction(new C_ADDIW(this)); + addSupportedInstruction(new C_ADDW(this)); + addSupportedInstruction(new C_AND(this)); + addSupportedInstruction(new C_ANDI(this)); + addSupportedInstruction(new C_BEQZ(this)); + addSupportedInstruction(new C_BNEZ(this)); + addSupportedInstruction(new C_EBREAK(this)); + addSupportedInstruction(new C_J(this)); +#ifdef RV32C_ONLY + addSupportedInstruction(new C_JAL(this)); +#endif + addSupportedInstruction(new C_JALR(this)); + addSupportedInstruction(new C_JR(this)); + addSupportedInstruction(new C_LD(this)); + addSupportedInstruction(new C_LDSP(this)); + addSupportedInstruction(new C_LWSP(this)); + addSupportedInstruction(new C_LI(this)); + addSupportedInstruction(new C_LUI(this)); + addSupportedInstruction(new C_LW(this)); + addSupportedInstruction(new C_MV(this)); + addSupportedInstruction(new C_NOP(this)); + addSupportedInstruction(new C_OR(this)); + addSupportedInstruction(new C_SD(this)); + addSupportedInstruction(new C_SDSP(this)); + addSupportedInstruction(new C_SLLI(this)); + addSupportedInstruction(new C_SRAI(this)); + addSupportedInstruction(new C_SRLI(this)); + addSupportedInstruction(new C_SUB(this)); + addSupportedInstruction(new C_SUBW(this)); + addSupportedInstruction(new C_SW(this)); + addSupportedInstruction(new C_SWSP(this)); + addSupportedInstruction(new C_XOR(this)); + + uint64_t isa = portCSR_.read(CSR_misa).val; + portCSR_.write(CSR_misa, isa | (1LL << ('C' - 'C'))); +} + +} // namespace debugger
src/cpu_fnc_plugin/riscv-ext-c.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/cpu_fnc_plugin/srcproc/srcproc.cpp =================================================================== --- src/cpu_fnc_plugin/srcproc/srcproc.cpp (nonexistent) +++ src/cpu_fnc_plugin/srcproc/srcproc.cpp (revision 5) @@ -0,0 +1,1461 @@ +/** + * @file + * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Source code processor class declaration. + */ + +#include "srcproc.h" +#include +#include + +namespace debugger { + +/** Class registration in the Core */ +enum ESymbInfo { + SymbInfo_Name, + SymbInfo_Address, + SymbInfo_Total, +}; + +const char *const *RN = IREGS_NAMES; + +int opcode_0x00(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x03(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x04(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x05(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x06(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x08(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x0C(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x0D(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x0E(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x18(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x19(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x1B(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); +int opcode_0x1C(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); + +int C_ADDI16SP_LUI(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_ADDI4SPN(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_BEQZ(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_BNEZ(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_J(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_JAL_ADDIW(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_JR_MV_EBREAK_JALR_ADD(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_LD(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_LI(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_LDSP(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_LW(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_LWSP(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_MATH(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_NOP_ADDI(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_SD(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_SDSP(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_SLLI(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_SW(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); +int C_SWSP(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment); + + +RiscvSourceService::RiscvSourceService(const char *name) : IService(name) { + registerInterface(static_cast(this)); + memset(tblOpcode1_, 0, sizeof(tblOpcode1_)); + tblOpcode1_[0x00] = &opcode_0x00; + tblOpcode1_[0x03] = &opcode_0x03; + tblOpcode1_[0x04] = &opcode_0x04; + tblOpcode1_[0x05] = &opcode_0x05; + tblOpcode1_[0x06] = &opcode_0x06; + tblOpcode1_[0x08] = &opcode_0x08; + tblOpcode1_[0x0C] = &opcode_0x0C; + tblOpcode1_[0x0D] = &opcode_0x0D; + tblOpcode1_[0x0E] = &opcode_0x0E; + tblOpcode1_[0x18] = &opcode_0x18; + tblOpcode1_[0x19] = &opcode_0x19; + tblOpcode1_[0x1B] = &opcode_0x1B; + tblOpcode1_[0x1C] = &opcode_0x1C; + + memset(tblCompressed_, 0, sizeof(tblCompressed_)); + // page 82, table 12.5 " RISC-V spec. v2.2" + // Compute index as hash = {[15:13],[1:0]} + tblCompressed_[0x00] = &C_ADDI4SPN; + tblCompressed_[0x01] = &C_NOP_ADDI; + tblCompressed_[0x02] = &C_SLLI; + tblCompressed_[0x05] = &C_JAL_ADDIW; + tblCompressed_[0x08] = &C_LW; + tblCompressed_[0x09] = &C_LI; + tblCompressed_[0x0A] = &C_LWSP; + tblCompressed_[0x0C] = &C_LD; + tblCompressed_[0x0D] = &C_ADDI16SP_LUI; + tblCompressed_[0x0E] = &C_LDSP; + tblCompressed_[0x11] = &C_MATH; + tblCompressed_[0x12] = &C_JR_MV_EBREAK_JALR_ADD; + tblCompressed_[0x15] = &C_J; + tblCompressed_[0x18] = &C_SW; + tblCompressed_[0x19] = &C_BEQZ; + tblCompressed_[0x1A] = &C_SWSP; + tblCompressed_[0x1C] = &C_SD; + tblCompressed_[0x1D] = &C_BNEZ; + tblCompressed_[0x1E] = &C_SDSP; + + brList_.make_list(0); + symbolListSortByName_.make_list(0); + symbolListSortByAddr_.make_list(0); +} + +RiscvSourceService::~RiscvSourceService() { +} + +void RiscvSourceService::postinitService() { +} + +void RiscvSourceService::addFileSymbol(const char *name, uint64_t addr, + int sz) { + AttributeType symb(Attr_List); + symb.make_list(Symbol_Total); + symb[Symbol_Name].make_string(name); + symb[Symbol_Addr].make_uint64(addr); + symb[Symbol_Size].make_int64(sz); + + symbolListSortByName_.add_to_list(&symb); + symbolListSortByName_.sort(Symbol_Name); + + symbolListSortByAddr_.add_to_list(&symb); + symbolListSortByAddr_.sort(Symbol_Addr); +} + +void RiscvSourceService::addFunctionSymbol(const char *name, + uint64_t addr, int sz) { + addFileSymbol(name, addr, sz); +} + +void RiscvSourceService::addDataSymbol(const char *name, uint64_t addr, + int sz) { + addFileSymbol(name, addr, sz); +} + +void RiscvSourceService::clearSymbols() { + symbolListSortByName_.make_list(0); + symbolListSortByAddr_.make_list(0); +} + +void RiscvSourceService::addSymbols(AttributeType *list) { + for (unsigned i = 0; i < list->size(); i++) { + AttributeType &item = (*list)[i]; + symbolListSortByName_.add_to_list(&item); + symbolListSortByAddr_.add_to_list(&item); + } + symbolListSortByName_.sort(Symbol_Name); + symbolListSortByAddr_.sort(Symbol_Addr); +} + +void RiscvSourceService::addressToSymbol(uint64_t addr, AttributeType *info) { + uint64_t sadr, send; + int sz = static_cast(symbolListSortByAddr_.size()); + + info->make_list(SymbInfo_Total); + (*info)[SymbInfo_Name].make_string(""); + (*info)[SymbInfo_Address].make_uint64(0); + if (sz == 0) { + return; + } + sadr = symbolListSortByAddr_[0u][Symbol_Addr].to_uint64(); + if (addr < sadr) { + return; + } + + bool search = true; + int dist, pos = sz / 2; + dist = pos; + while (search) { + AttributeType &symb = symbolListSortByAddr_[pos]; + sadr = symb[Symbol_Addr].to_uint64(); + if (pos < static_cast(symbolListSortByAddr_.size()) - 1) { + send = symbolListSortByAddr_[pos + 1][Symbol_Addr].to_uint64(); + } else { + send = sadr + symb[Symbol_Size].to_uint64(); + } + if (sadr <= addr && addr < send) { + (*info)[SymbInfo_Name] = symb[Symbol_Name]; + (*info)[SymbInfo_Address].make_uint64(addr - sadr); + return; + } + + if (addr < sadr) { + if (dist == 0 || pos == 0) { + search = false; + } else if (dist == 1) { + dist = 0; + pos--; + } else { + int incr = dist / 2; + pos -= incr; + dist = (dist / 2) + (dist & 0x1); + if (pos < 0) { + pos = 0; + } + } + } else { + if (dist == 0 || pos == (sz - 1)) { + search = false; + } else if (dist == 1) { + dist = 0; + pos++; + } else { + int incr = dist / 2; + pos += incr; + dist = (dist / 2) + (dist & 0x1); + if (pos >= sz) { + pos = sz - 1; + } + } + } + } +} + +int RiscvSourceService::symbol2Address(const char *name, uint64_t *addr) { + for (unsigned i = 0; i < symbolListSortByName_.size(); i++) { + AttributeType &item = symbolListSortByName_[i]; + if (item[Symbol_Name].is_equal(name)) { + *addr = item[Symbol_Addr].to_uint64(); + return 0; + } + } + return -1; +} + +void RiscvSourceService::registerBreakpoint(uint64_t addr, uint64_t flags, + uint64_t instr) { + AttributeType item; + item.make_list(BrkList_Total); + item[BrkList_address].make_uint64(addr); + item[BrkList_flags].make_uint64(flags); + item[BrkList_instr].make_uint64(instr); + + bool not_found = true; + for (unsigned i = 0; i < brList_.size(); i++) { + AttributeType &br = brList_[i]; + if (addr == br[BrkList_address].to_uint64()) { + not_found = false; + } + } + if (not_found) { + brList_.add_to_list(&item); + } +} + +int RiscvSourceService::unregisterBreakpoint(uint64_t addr, uint64_t *flags, + uint64_t *instr) { + for (unsigned i = 0; i < brList_.size(); i++) { + AttributeType &br = brList_[i]; + if (addr == br[BrkList_address].to_uint64()) { + *flags = br[BrkList_flags].to_uint64(); + *instr = br[BrkList_instr].to_uint64(); + brList_.remove_from_list(i); + return 0; + } + } + return 1; +} + +void RiscvSourceService::getBreakpointList(AttributeType *list) { + if (!list->is_list() || list->size() != brList_.size()) { + list->make_list(brList_.size()); + } + + for (unsigned i = 0; i < brList_.size(); i++) { + AttributeType &item = (*list)[i]; + AttributeType &br = brList_[i]; + if (!item.is_list() || item.size() != 3) { + item.make_list(BrkList_Total); + } + item[BrkList_address] = br[BrkList_address]; + item[BrkList_flags] = br[BrkList_flags]; + item[BrkList_instr] = br[BrkList_instr]; + } +} + +bool RiscvSourceService::isBreakpoint(uint64_t addr, AttributeType *outbr) { + for (unsigned i = 0; i < brList_.size(); i++) { + uint64_t bradr = brList_[i][BrkList_address].to_uint64(); + if (addr == bradr) { + *outbr = brList_[i]; + return true; + } + } + return false; +} + +int RiscvSourceService::disasm(uint64_t pc, + uint8_t *data, + int offset, + AttributeType *mnemonic, + AttributeType *comment) { + int oplen; + if ((data[offset] & 0x3) < 3) { + Reg16Type val; + uint32_t hash; + val.word = *reinterpret_cast(&data[offset]); + hash = ((val.word >> 11) & 0x1C) | (val.word & 0x3); + oplen = 2; + if (tblCompressed_[hash]) { + return tblCompressed_[hash](static_cast(this), + pc + static_cast(offset), + val, + mnemonic, + comment); + } + } else if ((data[offset] & 0x3) == 0x3) { + uint32_t val = *reinterpret_cast(&data[offset]); + uint32_t opcode1 = (val >> 2) & 0x1f; + oplen = 4; + if (tblOpcode1_[opcode1]) { + return tblOpcode1_[opcode1](static_cast(this), + pc + static_cast(offset), + val, + mnemonic, + comment); + } + } + + mnemonic->make_string("unimpl"); + comment->make_string(""); + return oplen; +} + +void RiscvSourceService::disasm(uint64_t pc, + AttributeType *idata, + AttributeType *asmlist) { + asmlist->make_list(0); + if (!idata->is_data()) { + return; + } + uint8_t *data = idata->data(); + + AttributeType asm_item, symb_item, info, brpoint; + asm_item.make_list(ASM_Total); + symb_item.make_list(3); + asm_item[ASM_list_type].make_int64(AsmList_disasm); + symb_item[ASM_list_type].make_int64(AsmList_symbol); + uint64_t off = 0; + Reg64Type code; + int codesz; + + while (static_cast(off) < idata->size()) { + code.val = *reinterpret_cast(&data[off]); + + addressToSymbol(pc + off, &info); + if (info[SymbInfo_Name].size() != 0 && + info[SymbInfo_Address].to_int() == 0) { + symb_item[1].make_uint64(pc + off); + symb_item[2].make_string(info[SymbInfo_Name].to_string()); + asmlist->add_to_list(&symb_item); + } + asm_item[ASM_addrline].make_uint64(pc + off); + asm_item[ASM_breakpoint].make_boolean(false); + asm_item[ASM_label].make_string(""); + + if (isBreakpoint(pc + off, &brpoint)) { + asm_item[ASM_breakpoint].make_boolean(true); + if (!(brpoint[BrkList_flags].to_uint64() & BreakFlag_HW)) { + code.val = brpoint[BrkList_instr].to_uint32(); + } + } + codesz = disasm(pc + off, + code.buf, + 0, + &asm_item[ASM_mnemonic], + &asm_item[ASM_comment]); + +#if 1 + uint64_t swap = code.val; + if (codesz == 2) { + swap = code.buf16[0]; + } +#else + uint64_t swap = 0; + for (int i = 0; i < codesz; i++) { + swap = (swap << 8) | code.buf[i]; + } +#endif + asm_item[ASM_code].make_uint64(swap); + asm_item[ASM_codesize].make_uint64(codesz); + asmlist->add_to_list(&asm_item); + off += codesz; + } +} + +int opcode_0x00(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_I_type i; + int32_t imm; + + i.value = code; + imm = static_cast(code) >> 20; + switch (i.bits.funct3) { + case 0: + RISCV_sprintf(tstr, sizeof(tstr), "lb %s,%d(%s)", + RN[i.bits.rd], imm, RN[i.bits.rs1]); + break; + case 1: + RISCV_sprintf(tstr, sizeof(tstr), "lh %s,%d(%s)", + RN[i.bits.rd], imm, RN[i.bits.rs1]); + break; + case 2: + RISCV_sprintf(tstr, sizeof(tstr), "lw %s,%d(%s)", + RN[i.bits.rd], imm, RN[i.bits.rs1]); + break; + case 3: + RISCV_sprintf(tstr, sizeof(tstr), "ld %s,%d(%s)", + RN[i.bits.rd], imm, RN[i.bits.rs1]); + break; + case 4: + RISCV_sprintf(tstr, sizeof(tstr), "lbu %s,%d(%s)", + RN[i.bits.rd], imm, RN[i.bits.rs1]); + break; + case 5: + RISCV_sprintf(tstr, sizeof(tstr), "lhu %s,%d(%s)", + RN[i.bits.rd], imm, RN[i.bits.rs1]); + break; + case 6: + RISCV_sprintf(tstr, sizeof(tstr), "lwu %s,%d(%s)", + RN[i.bits.rd], imm, RN[i.bits.rs1]); + break; + default:; + } + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +int opcode_0x03(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_R_type r; + + r.value = code; + switch (r.bits.funct3) { + case 0: + RISCV_sprintf(tstr, sizeof(tstr), "%s", "fence"); + break; + case 1: + RISCV_sprintf(tstr, sizeof(tstr), "%s", "fence_i"); + break; + default:; + } + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +int opcode_0x04(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_I_type i; + int32_t imm; + + i.value = code; + imm = static_cast(code) >> 20; + switch (i.bits.funct3) { + case 0: + if (imm == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "mv %s,%s", + RN[i.bits.rd], RN[i.bits.rs1]); + } else if (i.bits.rs1 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "li %s,%d", + RN[i.bits.rd], imm); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "addi %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + } + break; + case 1: + RISCV_sprintf(tstr, sizeof(tstr), "slli %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + break; + case 2: + RISCV_sprintf(tstr, sizeof(tstr), "slti %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + break; + case 3: + RISCV_sprintf(tstr, sizeof(tstr), "sltiu %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + break; + case 4: + RISCV_sprintf(tstr, sizeof(tstr), "xori %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + break; + case 5: + if ((code >> 26) == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "srli %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + } else if ((code >> 26) == 0x20) { + RISCV_sprintf(tstr, sizeof(tstr), "srai %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + } + break; + case 6: + RISCV_sprintf(tstr, sizeof(tstr), "ori %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + break; + case 7: + RISCV_sprintf(tstr, sizeof(tstr), "andi %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + break; + default:; + } + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +int opcode_0x05(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_U_type u; + uint64_t imm64; + + u.value = code; + imm64 = u.bits.imm31_12 << 12; + if (imm64 & (1LL << 31)) { + imm64 |= EXT_SIGN_32; + } + RISCV_sprintf(tstr, sizeof(tstr), "auipc %s,0x%" RV_PRI64 "x", + RN[u.bits.rd], imm64); + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +int opcode_0x06(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_I_type i; + int32_t imm; + + i.value = code; + imm = static_cast(code) >> 20; + switch (i.bits.funct3) { + case 0: + RISCV_sprintf(tstr, sizeof(tstr), "addiw %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + break; + case 1: + RISCV_sprintf(tstr, sizeof(tstr), "slliw %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + break; + case 5: + if ((code >> 25) == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "srliw %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + } else if ((code >> 25) == 0x20) { + RISCV_sprintf(tstr, sizeof(tstr), "sraiw %s,%s,%d", + RN[i.bits.rd], RN[i.bits.rs1], imm); + } + break; + default:; + } + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +int opcode_0x08(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_S_type s; + int32_t imm; + s.value = code; + imm = (s.bits.imm11_5 << 5) | s.bits.imm4_0; + if (imm & 0x800) { + imm |= EXT_SIGN_12; + } + switch (s.bits.funct3) { + case 0: + RISCV_sprintf(tstr, sizeof(tstr), "sb %s,%d(%s)", + RN[s.bits.rs2], imm, RN[s.bits.rs1]); + break; + case 1: + RISCV_sprintf(tstr, sizeof(tstr), "sh %s,%d(%s)", + RN[s.bits.rs2], imm, RN[s.bits.rs1]); + break; + case 2: + RISCV_sprintf(tstr, sizeof(tstr), "sw %s,%d(%s)", + RN[s.bits.rs2], imm, RN[s.bits.rs1]); + break; + case 3: + RISCV_sprintf(tstr, sizeof(tstr), "sd %s,%d(%s)", + RN[s.bits.rs2], imm, RN[s.bits.rs1]); + break; + default:; + } + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + + +int opcode_0x0C(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_R_type r; + r.value = code; + switch (r.bits.funct3) { + case 0: + if (r.bits.funct7 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "add %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } else if (r.bits.funct7 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "mul %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } else if (r.bits.funct7 == 0x20) { + RISCV_sprintf(tstr, sizeof(tstr), "sub %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } + break; + case 1: + RISCV_sprintf(tstr, sizeof(tstr), "sll %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + break; + case 2: + RISCV_sprintf(tstr, sizeof(tstr), "slt %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + break; + case 3: + RISCV_sprintf(tstr, sizeof(tstr), "sltu %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + break; + case 4: + if (r.bits.funct7 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "xor %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } else if (r.bits.funct7 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "div %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } + break; + case 5: + if (r.bits.funct7 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "srl %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } else if (r.bits.funct7 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "divu %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } else if (r.bits.funct7 == 0x20) { + RISCV_sprintf(tstr, sizeof(tstr), "sra %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } + break; + case 6: + if (r.bits.funct7 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "or %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } else if (r.bits.funct7 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "rem %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } + break; + case 7: + if (r.bits.funct7 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "and %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } else if (r.bits.funct7 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "remu %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } + break; + default:; + } + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +int opcode_0x0D(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_U_type u; + u.value = code; + RISCV_sprintf(tstr, sizeof(tstr), "lui %s,0x%x", + RN[u.bits.rd], u.bits.imm31_12); + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +int opcode_0x0E(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_R_type r; + + r.value = code; + switch (r.bits.funct3) { + case 0: + if (r.bits.funct7 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "addw %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } else if (r.bits.funct7 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "mulw %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } else if (r.bits.funct7 == 0x20) { + RISCV_sprintf(tstr, sizeof(tstr), "subw %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } + break; + case 1: + RISCV_sprintf(tstr, sizeof(tstr), "sllw %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + break; + case 4: + if (r.bits.funct7 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "divw %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } + break; + case 5: + if (r.bits.funct7 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "srlw %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } else if (r.bits.funct7 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "divuw %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } else if (r.bits.funct7 == 0x20) { + RISCV_sprintf(tstr, sizeof(tstr), "sraw %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } + break; + case 6: + if (r.bits.funct7 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "remw %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } + break; + case 7: + if (r.bits.funct7 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "remuw %s,%s,%s", + RN[r.bits.rd], RN[r.bits.rs1], RN[r.bits.rs2]); + } + break; + default:; + } + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +int opcode_0x18(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_SB_type sb; + uint64_t imm64; + + sb.value = code; + imm64 = (sb.bits.imm12 << 12) | (sb.bits.imm11 << 11) + | (sb.bits.imm10_5 << 5) | (sb.bits.imm4_1 << 1); + if (sb.bits.imm12) { + imm64 |= EXT_SIGN_12; + } + imm64 += pc; + switch (sb.bits.funct3) { + case 0: + if (sb.bits.rs2 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "beqz %s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], imm64); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "beq %s,%s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], RN[sb.bits.rs2], imm64); + } + break; + case 1: + if (sb.bits.rs2 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "bnez %s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], imm64); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "bne %s,%s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], RN[sb.bits.rs2], imm64); + } + break; + case 4: + if (sb.bits.rs2 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "bltz %s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], imm64); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "blt %s,%s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], RN[sb.bits.rs2], imm64); + } + break; + case 5: + if (sb.bits.rs2 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "bgez %s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], imm64); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "bge %s,%s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], RN[sb.bits.rs2], imm64); + } + break; + case 6: + if (sb.bits.rs2 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "bltuz %s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], imm64); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "bltu %s,%s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], RN[sb.bits.rs2], imm64); + } + break; + case 7: + if (sb.bits.rs2 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "bgeuz %s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], imm64); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "bgeu %s,%s,%08" RV_PRI64 "x", + RN[sb.bits.rs1], RN[sb.bits.rs2], imm64); + } + break; + default:; + } + + if (isrc) { + AttributeType info; + isrc->addressToSymbol(imm64, &info); + if (info[0u].size()) { + if (info[1].to_uint32() == 0) { + RISCV_sprintf(tcomm, sizeof(tcomm), "%s", + info[0u].to_string()); + } else { + RISCV_sprintf(tcomm, sizeof(tcomm), "%s+%xh", + info[0u].to_string(), info[1].to_uint32()); + } + } + } + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +int opcode_0x19(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_I_type i; + uint64_t imm64; + + i.value = code; + imm64 = static_cast(code) >> 20; + if (imm64 == 0) { + if (i.bits.rs1 == Reg_ra) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "ret"); + } else if (i.bits.rd == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "jr %s", + RN[i.bits.rs1]); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "jalr %s", + RN[i.bits.rs1]); + } + } else { + RISCV_sprintf(tstr, sizeof(tstr), "jalr %" RV_PRI64 "d,(%s)", + imm64, RN[i.bits.rs1]); + } + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +int opcode_0x1B(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_UJ_type uj; + uint64_t imm64; + + uj.value = code; + imm64 = 0; + if (uj.bits.imm20) { + imm64 = 0xfffffffffff00000LL; + } + imm64 |= (uj.bits.imm19_12 << 12); + imm64 |= (uj.bits.imm11 << 11); + imm64 |= (uj.bits.imm10_1 << 1); + if (uj.bits.rd) { + RISCV_sprintf(tstr, sizeof(tstr), "jal ra,%08" RV_PRI64 "x", + pc + imm64); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "j %08" RV_PRI64 "x", + pc + imm64); + } + + if (isrc) { + AttributeType info; + isrc->addressToSymbol(pc + imm64, &info); + if (info[0u].size()) { + if (info[1].to_uint32() == 0) { + RISCV_sprintf(tcomm, sizeof(tcomm), "%s", + info[0u].to_string()); + } else { + RISCV_sprintf(tcomm, sizeof(tcomm), "%s+%xh", + info[0u].to_string(), info[1].to_uint32()); + } + } + } + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +int opcode_0x1C(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_I_type i; + uint32_t imm; + + i.value = code; + imm = static_cast(code) >> 20; + + switch (i.bits.funct3) { + case 0: + if (code == 0x00000073) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "ecall"); + } else if (code == 0x00100073) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "ebreak"); + } else if (code == 0x00200073) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "uret"); + } else if (code == 0x10200073) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "sret"); + } else if (code == 0x20200073) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "hret"); + } else if (code == 0x30200073) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "mret"); + } + break; + case 1: + if (i.bits.rd == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "csrw 0x%x,%s", + imm, RN[i.bits.rs1]); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "csrrw %s,0x%x,%s", + RN[i.bits.rd], imm, RN[i.bits.rs1]); + } + break; + case 2: + if (i.bits.rs1 == 0) { + // Read + RISCV_sprintf(tstr, sizeof(tstr), "csrr %s,0x%x", + RN[i.bits.rd], imm); + } else if (i.bits.rd == 0) { + // Set + RISCV_sprintf(tstr, sizeof(tstr), "csrs 0x%x,%s", + imm, RN[i.bits.rs1]); + } else { + // Read and set + RISCV_sprintf(tstr, sizeof(tstr), "csrrs %s,0x%x,%s", + RN[i.bits.rd], imm, RN[i.bits.rs1]); + } + break; + case 3: + if (i.bits.rd == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "csrc 0x%x,%s", + imm, RN[i.bits.rs1]); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "csrrc %s,0x%x,%s", + RN[i.bits.rd], imm, RN[i.bits.rs1]); + } + break; + case 5: + if (i.bits.rd == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "csrwi 0x%x,0x%x", + imm, i.bits.rs1); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "csrrwi %s,0x%x,0x%x", + RN[i.bits.rd], imm, i.bits.rs1); + } + break; + case 6: + if (i.bits.rd == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "csrsi 0x%x,0x%x", + imm, i.bits.rs1); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "csrrsi %s,0x%x,0x%x", + RN[i.bits.rd], imm, i.bits.rs1); + } + break; + case 7: + if (i.bits.rd == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "csrci 0x%x,0x%x", + imm, i.bits.rs1); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "csrrci %s,0x%x,0x%x", + RN[i.bits.rd], imm, i.bits.rs1); + } + break; + default:; + } + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 4; +} + +/** + * C-extension disassembler + */ +int C_JR_MV_EBREAK_JALR_ADD(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_CR_type u; + u.value = code.word; + if (u.bits.funct4 == 0x8) { + if (u.bits.rdrs1 && !u.bits.rs2) { + if (u.bits.rdrs1 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "ret"); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "jr %s", + RN[u.bits.rdrs1]); + } + } else { + RISCV_sprintf(tstr, sizeof(tstr), "mv %s,%s", + RN[u.bits.rdrs1], RN[u.bits.rs2]); + } + } else { + if (!u.bits.rdrs1 && !u.bits.rs2) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "ebreak"); + } else if (u.bits.rdrs1 && !u.bits.rs2) { + RISCV_sprintf(tstr, sizeof(tstr), "jalr ra,%s,0", + RN[u.bits.rdrs1]); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "add %s,%s,%s", + RN[u.bits.rdrs1], RN[u.bits.rdrs1], RN[u.bits.rs2]); + } + } + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_NOP_ADDI(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CI_type u; + u.value = code.word; + uint64_t imm = u.bits.imm; + if (u.bits.imm6) { + imm |= EXT_SIGN_6; + } + if (u.value == 0x1) { + RISCV_sprintf(tstr, sizeof(tstr), "%s", "nop"); + } else { + RISCV_sprintf(tstr, sizeof(tstr), "addi %s,%s,%" RV_PRI64 "d", + RN[u.bits.rdrs], RN[u.bits.rdrs], imm); + } + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_ADDI16SP_LUI(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CI_type u; + u.value = code.word; + if (u.spbits.sp == 0x2) { + uint64_t imm = (u.spbits.imm8_7 << 3) | (u.spbits.imm6 << 2) + | (u.spbits.imm5 << 1) | u.spbits.imm4; + if (u.spbits.imm9) { + imm |= EXT_SIGN_6; + } + imm <<= 4; + RISCV_sprintf(tstr, sizeof(tstr), "addi sp,sp,%" RV_PRI64 "d", + imm); + } else { + uint64_t imm = u.bits.imm; + if (u.bits.imm6) { + imm |= EXT_SIGN_6; + } + imm <<= 12; + RISCV_sprintf(tstr, sizeof(tstr), "lui %s,0x%x", + RN[u.bits.rdrs], static_cast(imm)); + + } + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_ADDI4SPN(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimp"; + char tcomm[128] = ""; + ISA_CIW_type u; + u.value = code.word; + uint64_t imm = (u.bits.imm9_6 << 4) | (u.bits.imm5_4 << 2) + | (u.bits.imm3 << 1) | u.bits.imm2; + imm <<= 2; + if (code.word) { + RISCV_sprintf(tstr, sizeof(tstr), "addi %s,sp,%" RV_PRI64 "d", + RN[8 + u.bits.rd], imm); + } + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_JAL_ADDIW(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CI_type u; + u.value = code.word; + int64_t imm = u.bits.imm; + if (u.bits.imm6) { + imm |= EXT_SIGN_6; + } + // JAL is th RV32C only instruction + RISCV_sprintf(tstr, sizeof(tstr), "addiw %s,%s,%" RV_PRI64 "d", + RN[u.bits.rdrs], RN[u.bits.rdrs], imm); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_LD(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CL_type u; + u.value = code.word; + uint32_t off = (u.bits.imm27 << 4) | (u.bits.imm6 << 3) | u.bits.imm5_3; + off <<= 3; + + RISCV_sprintf(tstr, sizeof(tstr), "ld %s,%d(%s)", + RN[8 + u.bits.rd], off, RN[8 + u.bits.rs1]); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_LDSP(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CI_type u; + u.value = code.word; + uint32_t off = (u.ldspbits.off8_6 << 3) | (u.ldspbits.off5 << 2) + | u.ldspbits.off4_3; + off <<= 3; + + RISCV_sprintf(tstr, sizeof(tstr), "ld %s,%d(sp)", + RN[u.ldspbits.rd], off); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_LI(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CI_type u; + u.value = code.word; + int64_t imm = u.bits.imm; + if (u.bits.imm6) { + imm |= EXT_SIGN_6; + } + + RISCV_sprintf(tstr, sizeof(tstr), "li %s,%" RV_PRI64 "d", + RN[u.bits.rdrs], imm); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_LW(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CL_type u; + u.value = code.word; + uint32_t off = (u.bits.imm6 << 4) | (u.bits.imm5_3 << 1) | u.bits.imm27; + off <<= 2; + + RISCV_sprintf(tstr, sizeof(tstr), "lw %s,%d(%s)", + RN[8 + u.bits.rd], off, RN[8 + u.bits.rs1]); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_LWSP(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CI_type u; + u.value = code.word; + uint32_t off = (u.lwspbits.off7_6 << 4) | (u.lwspbits.off5 << 3) + | u.lwspbits.off4_2; + off <<= 2; + + RISCV_sprintf(tstr, sizeof(tstr), "lw %s,%d(sp)", + RN[u.lwspbits.rd], off); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_MATH(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128] = "unimpl"; + char tcomm[128] = ""; + ISA_CB_type u; + u.value = code.word; + uint32_t shamt = (u.shbits.shamt5 << 5) | u.shbits.shamt; + uint32_t imm = (u.bits.off7_6 << 3) | (u.bits.off2_1 << 1) | u.bits.off5; + + if (u.bits.off4_3 == 0) { + RISCV_sprintf(tstr, sizeof(tstr), "srli %s,%s,%d", + RN[8 + u.shbits.rd], RN[8 + u.shbits.rd], shamt); + } else if (u.bits.off4_3 == 1) { + RISCV_sprintf(tstr, sizeof(tstr), "srai %s,%s,%d", + RN[8 + u.shbits.rd], RN[8 + u.shbits.rd], shamt); + } else if (u.bits.off4_3 == 2) { + RISCV_sprintf(tstr, sizeof(tstr), "andi %s,%s,%d", + RN[8 + u.shbits.rd], RN[8 + u.shbits.rd], imm); + } else if (u.bits.off8 == 0) { + ISA_CS_type u2; + u2.value = code.word; + switch (u.bits.off7_6) { + case 0: + RISCV_sprintf(tstr, sizeof(tstr), "sub %s,%s,%s", + RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs2]); + break; + case 1: + RISCV_sprintf(tstr, sizeof(tstr), "xor %s,%s,%s", + RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs2]); + break; + case 2: + RISCV_sprintf(tstr, sizeof(tstr), "or %s,%s,%s", + RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs2]); + break; + default: + RISCV_sprintf(tstr, sizeof(tstr), "and %s,%s,%s", + RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs2]); + } + } else { + ISA_CS_type u2; + u2.value = code.word; + switch (u.bits.off7_6) { + case 0: + RISCV_sprintf(tstr, sizeof(tstr), "subw %s,%s,%s", + RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs2]); + break; + case 1: + RISCV_sprintf(tstr, sizeof(tstr), "addw %s,%s,%s", + RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs1], RN[8 + u2.bits.rs2]); + break; + default:; + } + } + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_J(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CJ_type u; + u.value = code.word; + uint64_t off = (u.bits.off10 << 9) | (u.bits.off9_8 << 7) + | (u.bits.off7 << 6) | (u.bits.off6 << 5) + | (u.bits.off5 << 4) | (u.bits.off4 << 3) + | u.bits.off3_1; + off <<= 1; + if (u.bits.off11) { + off |= EXT_SIGN_11; + } + RISCV_sprintf(tstr, sizeof(tstr), "j %" RV_PRI64 "x", pc + off); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_SD(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CS_type u; + u.value = code.word; + uint32_t off = (u.bits.imm27 << 4) | (u.bits.imm6 << 3) | u.bits.imm5_3; + off <<= 3; + + RISCV_sprintf(tstr, sizeof(tstr), "sd %s,%d(%s)", + RN[8 + u.bits.rs2], off, RN[8 + u.bits.rs1]); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_SDSP(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CSS_type u; + u.value = code.word; + uint32_t off = (u.dbits.imm8_6 << 3) | u.dbits.imm5_3; + off <<= 3; + + RISCV_sprintf(tstr, sizeof(tstr), "sd %s,%d(sp)", + RN[u.dbits.rs2], off); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_SW(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CS_type u; + u.value = code.word; + uint32_t off = (u.bits.imm6 << 4) | (u.bits.imm5_3 << 1) | u.bits.imm27; + off <<= 2; + + RISCV_sprintf(tstr, sizeof(tstr), "sw %s,%d(%s)", + RN[8 + u.bits.rs2], off, RN[8 + u.bits.rs1]); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_SWSP(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CSS_type u; + u.value = code.word; + uint32_t off = (u.wbits.imm7_6 << 4) | u.wbits.imm5_2; + off <<= 2; + + RISCV_sprintf(tstr, sizeof(tstr), "sw %s,%d(sp)", + RN[u.dbits.rs2], off); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_BEQZ(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CB_type u; + u.value = code.word; + uint64_t imm = (u.bits.off7_6 << 5) | (u.bits.off5 << 4) + | (u.bits.off4_3 << 2) | u.bits.off2_1; + imm <<= 1; + if (u.bits.off8) { + imm |= EXT_SIGN_9; + } + + RISCV_sprintf(tstr, sizeof(tstr), "beqz %s,%" RV_PRI64 "x", + RN[8 + u.bits.rs1], pc + imm); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_BNEZ(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CB_type u; + u.value = code.word; + uint64_t imm = (u.bits.off7_6 << 5) | (u.bits.off5 << 4) + | (u.bits.off4_3 << 2) | u.bits.off2_1; + imm <<= 1; + if (u.bits.off8) { + imm |= EXT_SIGN_9; + } + + RISCV_sprintf(tstr, sizeof(tstr), "bnez %s,%" RV_PRI64 "x", + RN[8 + u.bits.rs1], pc + imm); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +int C_SLLI(ISourceCode *isrc, uint64_t pc, Reg16Type code, + AttributeType *mnemonic, AttributeType *comment) { + char tstr[128]; + char tcomm[128] = ""; + ISA_CB_type u; + u.value = code.word; + uint32_t shamt = (u.shbits.shamt5 << 5) | u.shbits.shamt; + uint32_t idx = (u.shbits.funct2 << 3) | u.shbits.rd; + RISCV_sprintf(tstr, sizeof(tstr), "slli %s,%s,%d", + RN[idx], RN[idx], shamt); + + mnemonic->make_string(tstr); + comment->make_string(tcomm); + return 2; +} + +} // namespace debugger
src/cpu_fnc_plugin/srcproc/srcproc.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/cpu_fnc_plugin/srcproc/srcproc.h =================================================================== --- src/cpu_fnc_plugin/srcproc/srcproc.h (nonexistent) +++ src/cpu_fnc_plugin/srcproc/srcproc.h (revision 5) @@ -0,0 +1,83 @@ +/** + * @file + * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Source code processor class declaration. + */ + +#ifndef __DEBUGGER_SRCPROC_H__ +#define __DEBUGGER_SRCPROC_H__ + +#include +#include +#include "coreservices/isrccode.h" + +namespace debugger { + +typedef int (*disasm_opcode_f)(ISourceCode *isrc, uint64_t pc, uint32_t code, + AttributeType *mnemonic, AttributeType *comment); + +typedef int (*disasm_opcode16_f)(ISourceCode *isrc, uint64_t pc, + Reg16Type code, AttributeType *mnemonic, + AttributeType *comment); + +class RiscvSourceService : public IService, + public ISourceCode { +public: + explicit RiscvSourceService(const char *name); + virtual ~RiscvSourceService(); + + /** IService interface */ + virtual void postinitService(); + + /** ISourceCode interface */ + virtual void addFileSymbol(const char *name, uint64_t addr, int sz); + + virtual void addFunctionSymbol(const char *name, uint64_t addr, int sz); + + virtual void addDataSymbol(const char *name, uint64_t addr, int sz); + + virtual void addSymbols(AttributeType *list); + + virtual void clearSymbols(); + + virtual void getSymbols(AttributeType *list) { + *list = symbolListSortByName_; + } + + virtual void addressToSymbol(uint64_t addr, AttributeType *info); + + virtual int symbol2Address(const char *name, uint64_t *addr); + + virtual int disasm(uint64_t pc, + uint8_t *data, + int offset, + AttributeType *mnemonic, + AttributeType *comment); + virtual void disasm(uint64_t pc, + AttributeType *idata, + AttributeType *asmlist); + + virtual void registerBreakpoint(uint64_t addr, uint64_t flags, + uint64_t instr); + + virtual int unregisterBreakpoint(uint64_t addr, uint64_t *flags, + uint64_t *instr); + + virtual void getBreakpointList(AttributeType *list); + + virtual bool isBreakpoint(uint64_t addr, AttributeType *outbr); + +private: + disasm_opcode_f tblOpcode1_[32]; + disasm_opcode16_f tblCompressed_[32]; + AttributeType brList_; + AttributeType symbolListSortByName_; + AttributeType symbolListSortByAddr_; +}; + +DECLARE_CLASS(RiscvSourceService) + +} // namespace debugger + +#endif // __DEBUGGER_SRCPROC_H__
src/cpu_fnc_plugin/srcproc/srcproc.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/gui_plugin/GnssWidgets/PlotWidget.cpp =================================================================== --- src/gui_plugin/GnssWidgets/PlotWidget.cpp (nonexistent) +++ src/gui_plugin/GnssWidgets/PlotWidget.cpp (revision 5) @@ -0,0 +1,441 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Generic Plot drawer widget. + */ + +#include +#include "PlotWidget.h" +#include "moc_PlotWidget.h" + +namespace debugger { + +static const int MARGIN = 5; +static const char *PLOTS_COLORS[LINES_PER_PLOT_MAX] = { + "#007ACC", // nice blue color (msvc) + "#40C977", // green/blue color + "#CA5100", // nice orange color (msvc) + "#BD63C5", // violet + "#FFFFFF", // white color + "#FFFFFF", // white color + "#FFFFFF", // white color + "#FFFFFF" // white color +}; + +PlotWidget::PlotWidget(IGui *igui, QWidget *parent) + : QWidget(parent) { + igui_ = igui; + selectedEpoch = 0; + epochStart = 0; + epochTotal = 0; + lineTotal = 0; + trackLineIdx = 0; + pressed = Qt::NoButton; + waitingResp_ = false; + + setFocusPolicy(Qt::ClickFocus); + + contextMenu = new QMenu(this); + contextMenu->addAction( + tr("Clear zoom"), this, SLOT(slotActionZoomClear())); + + setContextMenuPolicy(Qt::CustomContextMenu); + connect(this, SIGNAL(customContextMenuRequested(const QPoint &)), + SLOT(slotRightClickMenu(const QPoint &))); + + connect(this, SIGNAL(signalCmdResponse()), SLOT(slotCmdResponse())); + + bkg1 = QColor(Qt::black); + cmd_.make_string("cpi"); + groupName = QString("NoGroupName"); + groupUnits = QString("clocks"); + defaultLineCfg.from_config("{" + "'Name':'NoName'," + "'Format':'%.1f'," + "'RingLength':256," + "'Color':'#FFFFFF'," + "'FixedMinY':true," + "'FixedMinYVal':0.0," + "'FixedMaxY':false," + "'FixedMaxYVal':0.0}"); +} + +CpiPlot::CpiPlot(IGui *igui, QWidget *parent) : PlotWidget(igui, parent) { + cmd_.make_string("cpi"); + groupName = QString("CPI"); + groupUnits = QString("clocks"); + + defaultLineCfg["Color"].make_string(PLOTS_COLORS[0]); + defaultLineCfg["Name"].make_string("CPI"); + defaultLineCfg["Format"].make_string("%.2f"); + line_[0] = new LineCommon(defaultLineCfg); + lineTotal = 1; +} + +BusUtilPlot::BusUtilPlot(IGui *igui, QWidget *parent) + : PlotWidget(igui, parent) { + cmd_.make_string("busutil"); + groupName = QString("Bus Utilization"); + groupUnits = QString("percentage"); + + defaultLineCfg["FixedMaxY"].make_boolean(true); + defaultLineCfg["FixedMaxYVal"].make_floating(100.0); +} + + +PlotWidget::~PlotWidget() { + for (int i = 0; i < lineTotal; i++) { + delete line_[i]; + } +} + +void PlotWidget::handleResponse(AttributeType *req, + AttributeType *resp) { + response_ = *resp; + emit signalCmdResponse(); + waitingResp_ = false; +} + +void CpiPlot::slotCmdResponse() { + if (!response_.is_list() || response_.size() != 5) { + return; + } + line_[0]->append(response_[4].to_float()); + epochTotal = line_[0]->size(); + update(); +} + +void BusUtilPlot::slotCmdResponse() { + if (!response_.is_list()) { + return; + } + int mst_total = static_cast(response_.size()); + if (lineTotal < mst_total) { + char tstr[64]; + for (int i = lineTotal; i < mst_total; i++) { + RISCV_sprintf(tstr, sizeof(tstr), "mst[%d]", i); + defaultLineCfg["Name"].make_string(tstr); + defaultLineCfg["Color"].make_string(PLOTS_COLORS[i]); + line_[i] = new LineCommon(defaultLineCfg); + line_[i]->setPlotSize(rectPlot.width(), rectPlot.height()); + } + lineTotal = mst_total; + } + double wr, rd; + for (int i = 0; i < mst_total; i++) { + const AttributeType &mst = response_[i]; + if (!mst.is_list() || mst.size() != 2) { + continue; + } + wr = mst[0u].to_float(); + rd = mst[1].to_float(); + line_[i]->append(wr + rd); + } + epochTotal = line_[0]->size(); + update(); +} + +void PlotWidget::slotUpdateByTimer() { + if (waitingResp_ || pressed) { + return; + } + igui_->registerCommand(static_cast(this), + &cmd_, true); + waitingResp_ = true; +} + +void PlotWidget::renderAll() { + pixmap.fill(bkg1); + QPainter p(&pixmap); + + renderAxis(p); + + p.translate(rectPlot.topLeft()); + for (int lineIdx = 0; lineIdx < lineTotal; lineIdx++) { + renderLine(p, line_[lineIdx]); + } + + renderMarker(p); + renderInfoPanel(p); + + p.translate(-rectPlot.topLeft()); + renderSelection(p); + + p.end(); +} + +void PlotWidget::renderAxis(QPainter &p) { + p.setRenderHint(QPainter::Antialiasing, true); + + p.setPen(QPen(QColor(0x48,0x3D,0x8B))); // Color Dark State Blue: #483D8B + p.drawLine(rectPlot.bottomLeft(), rectPlot.bottomRight()); + p.drawLine(rectPlot.bottomLeft(), rectPlot.topLeft()); + + /** Draw Group name: */ + QSize groupTextSize = p.fontMetrics().size(Qt::TextDontClip, groupName); + QPoint groupTextPos = QPoint((width() - groupTextSize.width())/2, 0); + QRect groupTextRect = QRect(groupTextPos, groupTextSize); + p.setPen(QPen(QColor("#BFBFBF"))); + p.drawText(groupTextRect, Qt::AlignLeft, groupName); + + /** Draw Y-axis units: */ + p.rotate(-90.0); + groupTextSize = p.fontMetrics().size(Qt::TextDontClip, groupUnits); + groupTextPos = QPoint(-(height() + groupTextSize.width())/2, 2); + groupTextRect = QRect(groupTextPos, groupTextSize); + p.drawText(groupTextRect, Qt::AlignLeft, groupUnits); + p.rotate(90.0); +} + +void PlotWidget::renderLine(QPainter &p, LineCommon *pline) { + bool draw_line = false; + int x, y; + QPoint ptA, ptB; + QRect box(0, 0, 4, 4); + p.setPen(QColor(pline->getColor())); + pline->selectData(epochStart, epochTotal); + for (int i = epochStart; i < epochStart + epochTotal; i++) { + if (!pline->getNext(x, y)) { + draw_line = false; + continue; + } + box.moveTo(x - 2, y - 2); + p.drawRect(box); + + if (!draw_line) { + draw_line = true; + ptA = QPoint(x, y); + } else { + ptB = QPoint(x, y); + p.drawLine(ptA, ptB); + ptA = ptB; + } + } +} + +void PlotWidget::renderMarker(QPainter &p) { + if (!lineTotal) { + return; + } + LineCommon *pline = line_[trackLineIdx]; + int x, y; + p.setPen(Qt::red); + QRect box(0, 0, 6, 6); + if (pline->getXY(selectedEpoch, x, y)) { + /** + Vertial Marker line: + */ + p.setPen(QPen(QColor(0xff, 0, 0, 0xa0))); + QPoint ptA(x, 0); + QPoint ptB(x, rectPlot.height()); + p.drawLine(ptA, ptB); + + // Marker box + box.moveTo(x - 3, y - 3); + p.drawRect(box); + } +} + +void PlotWidget::renderSelection(QPainter &p) { + /** + Highlight selection when mouse pressed + */ + if (pressed == Qt::MiddleButton) { + p.setCompositionMode(QPainter::CompositionMode_Difference); + QRect rect(QPoint(pressStart.x(), rectPlot.top()), + QPoint(pressEnd.x(), rectPlot.bottom())); + p.fillRect(rect, Qt::white); + } +} + +void PlotWidget::renderInfoPanel(QPainter &p) { + char bufName[256]; + QFont fontPos; + // Save previous values: + QBrush oldBrush = p.brush(); + QPen oldPen = p.pen(); + QFont oldFont = p.font(); + + fontPos.setPixelSize(10); + p.setFont(fontPos); + + QSize infoNameSize; + QString name; + QString fullString; + fullString.sprintf("idx: %d\n", selectedEpoch); + + // Find the longest 'name : value' string among lines: + int NAME_WIDTH_MAX = rectPlot.width() / 2; + for (int i = 0; i < lineTotal; i++) { + LineCommon *pLine = line_[i]; + if (!pLine->getAxisValue(1, selectedEpoch, bufName, sizeof(bufName))) { + continue; + } + name.sprintf("%s: %s\n", pLine->getName(), bufName); + fullString += name; + } + infoNameSize = p.fontMetrics().size(Qt::TextDontClip, fullString); + /** Guard: to avoid wrong formatted string value */ + if (infoNameSize.width() > NAME_WIDTH_MAX) { + infoNameSize.setWidth(NAME_WIDTH_MAX); + } + + QPoint posPanel(rectPlot.width() - infoNameSize.width() - 5, 5); + + p.setPen(QPen(QColor("#450020"))); + p.setBrush(QBrush(QColor(0xff, 0xef, 0xd5, 0x80))); + + QRect rectPanel(posPanel, infoNameSize); + QRect textPanel = rectPanel; + rectPanel.setWidth(rectPanel.width() + 4); + rectPanel.setLeft(rectPanel.left() - 2); + p.drawRoundedRect(rectPanel, 2, 2); + p.drawText(textPanel, Qt::AlignLeft, fullString); + + // Restore: + p.setBrush(oldBrush); + p.setPen(oldPen); + p.setFont(oldFont); +} + +int PlotWidget::pix2epoch(QPoint pix) { + pix -= rectPlot.topLeft(); + if (pix.x() > rectPlot.width()) { + pix.setX(rectPlot.width()); + } + return line_[trackLineIdx]->getNearestByX(pix.x()); +} + +void PlotWidget::resizeEvent(QResizeEvent *ev) { + int w = ev->size().width(); + int h = ev->size().height(); + if (w == 0 || h == 0) { + return; + } + QSize pixmapSingleSize = QSize(w, h); + rectMargined.setTopLeft(QPoint(MARGIN, MARGIN)); + rectMargined.setBottomRight(QPoint(w - MARGIN, h - MARGIN)); + + QFontMetrics fm(font()); + int font_h = fm.height() + 4; + rectPlot = rectMargined; + rectPlot.setLeft(rectMargined.left() + font_h); + rectPlot.setTop(rectMargined.top() + font_h); + for (int i = 0; i < lineTotal; i++) { + line_[i]->setPlotSize(rectPlot.width(), rectPlot.height()); + } + + pixmap = QPixmap(pixmapSingleSize); +} + +void PlotWidget::paintEvent(QPaintEvent *event) { + renderAll(); + + QPainter p(this); + QPoint pos(0,0); + p.drawPixmap(pos, pixmap); + p.end(); +} + +void PlotWidget::mousePressEvent(QMouseEvent *event) { + setFocus(); + /** There're 2 methods: buttons() and button(): + buttons() is a multiple flag of button() + */ + pressed = event->button(); + if (pressed != Qt::LeftButton && pressed != Qt::MiddleButton) { + pressed = Qt::NoButton; + return; + } + + selectedEpoch = pix2epoch(event->pos()); + pressStart = event->pos(); +} + +void PlotWidget::mouseMoveEvent(QMouseEvent *event) { + if (!event->buttons()) { + return; + } + + if (pressed != Qt::NoButton) { + selectedEpoch = pix2epoch(event->pos()); + pressEnd = event->pos(); + update(); + } +} + +void PlotWidget::mouseReleaseEvent(QMouseEvent *) { + if (pressed == Qt::MiddleButton) { + /** Warning: changing of epochStart before epochEnd computed + * will raise an errors + */ + int tmpStart = pix2epoch(pressStart); + int tmpEnd = pix2epoch(pressEnd); + if (tmpStart < tmpEnd) { + epochStart = tmpStart; + epochTotal = tmpEnd - epochStart + 1; + } else if (tmpStart > tmpEnd) { + epochStart = tmpEnd; + epochTotal = tmpStart - epochStart + 1; + } + } + pressed = Qt::NoButton; + update(); +} + +void PlotWidget::keyPressEvent(QKeyEvent *event) { + switch (event->key()) { + case Qt::Key_Left: + if (selectedEpoch > epochStart) { + selectedEpoch--; + update(); + } + break; + case Qt::Key_Right: + if (selectedEpoch < (epochStart + epochTotal) - 1) { + selectedEpoch++; + update(); + } + break; + default:; + } +} + + +void PlotWidget::slotRightClickMenu(const QPoint &p) { + QPoint globalPos = mapToGlobal(p); + contextMenu->popup(globalPos); +} + +void PlotWidget::slotActionZoomClear() { + epochStart = 0; + epochTotal = line_[trackLineIdx]->size(); + update(); +} + + +double PlotWidget::borderUpValue(double v) { + double tmp; + if (v == 0) { + return 0; + } + + //double border = 1.0; + double x10 = 1.0; + if (v > 1.0) { + tmp = v; + while (tmp > 1.0) { + tmp /= 10.0; + x10 *= 10.0; + } + tmp *= 10.0; + tmp = (double)((int)tmp + 1); + x10 *= tmp; + + } else if (v < 1.0) { + } + return 0.0; +} + +} // namespace debugger
src/gui_plugin/GnssWidgets/PlotWidget.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/gui_plugin/GnssWidgets/PlotWidget.h =================================================================== --- src/gui_plugin/GnssWidgets/PlotWidget.h (nonexistent) +++ src/gui_plugin/GnssWidgets/PlotWidget.h (revision 5) @@ -0,0 +1,156 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Generic Plot drawer widget. + */ + +#pragma once + +#include "api_core.h" // MUST BE BEFORE QtWidgets.h or any other Qt header. +#include "attribute.h" +#include "igui.h" +#include "linecommon.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace debugger { + +static const int LINES_PER_PLOT_MAX = 8; + +class PlotWidget : public QWidget, + public IGuiCmdHandler { + Q_OBJECT + +public: + PlotWidget(IGui *igui, QWidget *parent = 0); + virtual ~PlotWidget(); + + /** IGuiCmdHandler */ + virtual void handleResponse(AttributeType *req, AttributeType *resp); + +public slots: + void slotUpdateByTimer(); + virtual void slotCmdResponse() =0; + void slotRightClickMenu(const QPoint &p); + void slotActionZoomClear(); + +signals: + void signalCmdResponse(); + +protected: + void resizeEvent(QResizeEvent *); + void paintEvent(QPaintEvent *ev); + void mousePressEvent(QMouseEvent *ev); + void mouseMoveEvent(QMouseEvent *ev); + void mouseReleaseEvent(QMouseEvent *ev); + void keyPressEvent(QKeyEvent *event); + +private: + void renderAll(); + void renderAxis(QPainter &p); + void renderLine(QPainter &p, LineCommon *pline); + void renderMarker(QPainter &p); + void renderSelection(QPainter &p); + void renderInfoPanel(QPainter &p); + int pix2epoch(QPoint pix); + + double borderUpValue(double v); + +protected: + IGui *igui_; + AttributeType cmd_; + AttributeType response_; + AttributeType defaultLineCfg; + + QColor bkg1; + + bool waitingResp_; + Qt::MouseButton pressed; + QPoint pressStart; /** Mouse Middle button start coordinates */ + QPoint pressEnd; /** Mouse Middle button end coordinates */ + + int epochStart; /** Draw data starting from this index */ + int epochTotal; /** Draw the following number of epochs */ + int selectedEpoch; + + double dmax; + double dmin; + QPixmap pixmap; + + int lineTotal; + int trackLineIdx; + LineCommon *line_[LINES_PER_PLOT_MAX]; + QString groupName; + QString groupUnits; + + QMenu *contextMenu; + QRect rectMargined; + QRect rectPlot; +}; + +class CpiPlot : public PlotWidget { +public: + CpiPlot(IGui *igui, QWidget *parent = 0); + virtual void slotCmdResponse(); +}; + +class BusUtilPlot : public PlotWidget { +public: + BusUtilPlot(IGui *igui, QWidget *parent = 0); + virtual void slotCmdResponse(); +}; + + +class PlotQMdiSubWindow : public QMdiSubWindow { + Q_OBJECT +public: + PlotQMdiSubWindow(IGui *igui, QMdiArea *area, QWidget *parent, + QAction *act) + : QMdiSubWindow(parent) { + setAttribute(Qt::WA_DeleteOnClose); + action_ = act; + area_ = area; + + setWindowTitle(act->text()); + setMinimumWidth(400); + setMinimumHeight(280); + QWidget *pnew1 = new CpiPlot(igui, this); + connect(parent, SIGNAL(signalUpdateByTimer()), + pnew1, SLOT(slotUpdateByTimer())); + + QWidget *pnew2 = new BusUtilPlot(igui, this); + connect(parent, SIGNAL(signalUpdateByTimer()), + pnew2, SLOT(slotUpdateByTimer())); + + setWindowIcon(act->icon()); + act->setChecked(true); + + layout()->setSpacing(2); + layout()->addWidget(pnew1); + layout()->addWidget(pnew2); + area_->addSubWindow(this); + show(); + } + +protected: + void closeEvent(QCloseEvent *event_) Q_DECL_OVERRIDE { + if (action_) { + action_->setChecked(false); + } + area_->removeSubWindow(this); + event_->accept(); + } +private: + QAction *action_; + QMdiArea *area_; +}; + +} // namespace debugger
src/gui_plugin/GnssWidgets/PlotWidget.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/gui_plugin/GnssWidgets/linecommon.cpp =================================================================== --- src/gui_plugin/GnssWidgets/linecommon.cpp (nonexistent) +++ src/gui_plugin/GnssWidgets/linecommon.cpp (revision 5) @@ -0,0 +1,213 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Plot's Line common class. + */ + +#include "api_core.h" +#include "linecommon.h" + +namespace debugger { + +LineCommon::LineCommon(AttributeType &descr) { + if (descr.is_dict()) { + descr_ = descr; + } else { + descr_.make_dict(); + descr_["Name"].make_string("NoName"); + descr_["Format"].make_string("%.1f"); + descr_["RingLength"].make_int64(256); + descr_["FixedMinY"].make_boolean(true); + descr_["FixedMinYVal"].make_floating(0.0); + descr_["FixedMaxY"].make_boolean(false); + descr_["FixedMaxYVal"].make_floating(0.0); + descr_["Color"].make_string("#FF0000"); + } + strcpy(color_, descr_["Color"].to_string()); + strcpy(format_, descr_["Format"].to_string()); + + plot_w = 0; + plot_h = 0; + dx = 0; + dy = 0; + sel_start_idx = 0; + sel_cnt = 0; + + is_ring_ = false; + len_ = 1024; + cnt_ = 0; + start_ = 0; + if (descr_["RingLength"].to_uint32()) { + is_ring_ = true; + len_ = descr_["RingLength"].to_int(); + } + + for (int i = 0; i < 2; i++) { + axis_[i].data = new double[len_]; + axis_[i].accum = 0; + axis_[i].minVal = 0; + axis_[i].maxVal = 0; + } +} + +const AttributeType &LineCommon::getDescription() { + return descr_; +} + +unsigned LineCommon::size() { + return cnt_; +} +void LineCommon::append(double y) { + append(size(), y); +} + +void LineCommon::append(double x, double y) { + if (cnt_ == 0) { + axis_[0].minVal = x; + axis_[0].maxVal = x; + axis_[1].minVal = y; + if (descr_["FixedMinY"].to_bool()) { + axis_[1].minVal = descr_["FixedMinYVal"].to_float(); + } + axis_[1].maxVal = y; + if (descr_["FixedMaxY"].to_bool()) { + axis_[1].maxVal = descr_["FixedMaxYVal"].to_float(); + } + } + + + int wridx; + if (is_ring_) { + if (cnt_ < len_) { + wridx = cnt_; + } else { + if (++start_ >= len_) { + start_ = 0; + } + wridx = start_ - 1; + if (wridx < 0) { + wridx += len_; + } + } + } else { + if (cnt_ >= len_) { + len_ *= 2; + for (int i = 0; i < 2; i++) { + double *tbuf = new double[len_]; + memcpy(tbuf, axis_[i].data, cnt_*sizeof(double)); + delete []axis_[i].data; + axis_[i].data = tbuf; + } + } + wridx = cnt_; + } + axis_[0].data[wridx] = x; + axis_[1].data[wridx] = y; + if (cnt_ < len_) { + cnt_++; + } + + // X-axis + axis_[0].accum += x; + if (x < axis_[0].minVal) { + axis_[0].minVal = x; + } + if (x > axis_[0].maxVal) { + axis_[0].maxVal = x; + } + + // Y-axis + axis_[1].accum += y; + if (y < axis_[1].minVal && !descr_["FixedMinY"].to_bool()) { + axis_[1].minVal = y; + } + if (y > axis_[1].maxVal && !descr_["FixedMaxY"].to_bool()) { + axis_[1].maxVal = y; + } +} + +void LineCommon::setPlotSize(int w, int h) { + plot_w = w; + plot_h = h; +} + + +void LineCommon::selectData(int start_idx, int total) { + sel_start_idx = start_idx; + sel_cnt = start_idx; + if (plot_w == 0 || plot_h == 0) { + dx = 0; + dy = 0; + return; + } + if (total > 1) { + dx = plot_w / static_cast(total - 1); + } else { + dx = 0; + } + double diff_y = axis_[1].maxVal - axis_[1].minVal; + if (diff_y) { + dy = plot_h / diff_y; + } else { + dy = 0; + } +} + +bool LineCommon::getNext(int &x, int &y) { + double val; + if (!getAxisValue(1, sel_cnt, val)) { + return false; + } + x = static_cast((sel_cnt - sel_start_idx) * dx + 0.5); + y = static_cast((axis_[1].maxVal - val) * dy + 0.5); + sel_cnt++; + return true; +} + +bool LineCommon::getXY(int idx, int &x, int &y) { + double val; + if (!getAxisValue(1, idx, val)) { + return false; + } + x = static_cast((idx - sel_start_idx) * dx + 0.5); + y = static_cast((axis_[1].maxVal - val) * dy + 0.5); + return true; +} + +int LineCommon::getNearestByX(int x) { + if (x < 0 || dx == 0) { + return sel_start_idx; + } + double idx = static_cast(x) / dx; + return sel_start_idx + static_cast(idx + 0.5); +} + +bool LineCommon::getAxisValue(int axis, int idx, double &outval) { + if (idx >= 0 && idx < cnt_) { + int n = (start_ + idx) % len_; + outval = axis_[axis].data[n]; + return true; + } + return false; +} + +bool LineCommon::getAxisValue(int axis, int idx, char *outbuf, size_t bufsz) { + if (idx >= 0 && idx < cnt_) { + int n = (start_ + idx) % len_; + double outval = axis_[axis].data[n]; + RISCV_sprintf(outbuf, bufsz, format_, outval); + return true; + } + return false; +} + +void LineCommon::getAxisMin(int axis, char *outbuf, size_t bufsz) { + RISCV_sprintf(outbuf, bufsz, format_, axis_[axis].minVal); +} + +void LineCommon::getAxisMax(int axis, char *outbuf, size_t bufsz) { + RISCV_sprintf(outbuf, bufsz, format_, axis_[axis].maxVal); +} + +} // namespace debugger
src/gui_plugin/GnssWidgets/linecommon.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/gui_plugin/GnssWidgets/linecommon.h =================================================================== --- src/gui_plugin/GnssWidgets/linecommon.h (nonexistent) +++ src/gui_plugin/GnssWidgets/linecommon.h (revision 5) @@ -0,0 +1,56 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Plot's Line common class. + */ +#pragma once + +#include "attribute.h" + +namespace debugger { + +class LineCommon { +public: + LineCommon(AttributeType &descr); + + const AttributeType &getDescription(); + unsigned size(); + void append(double y); + void append(double x, double y); + const char *getName() { return descr_["Name"].to_string(); } + const char *getColor() { return color_; } + + void setPlotSize(int w, int h); + void selectData(int start_idx, int total); + bool getNext(int &x, int &y); + bool getXY(int idx, int &x, int &y); + bool getAxisValue(int axis, int idx, double &outval); + bool getAxisValue(int axis, int idx, char *outbuf, size_t bufsz); + void getAxisMin(int axis, char *outbuf, size_t bufsz); + void getAxisMax(int axis, char *outbuf, size_t bufsz); + int getNearestByX(int x); + +private: + AttributeType descr_; + struct AxisType { + double *data; + double accum; + double minVal; + double maxVal; + } axis_[2]; + bool is_ring_; + int start_; + int cnt_; + int len_; + char color_[8]; + char format_[16]; + double plot_w; + double plot_h; + double dx; + double dy; + int sel_start_idx; + int sel_cnt; +}; + +} // namespace debugger
src/gui_plugin/GnssWidgets/linecommon.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/gui_plugin/GnssWidgets/moc_PlotWidget.h =================================================================== --- src/gui_plugin/GnssWidgets/moc_PlotWidget.h (nonexistent) +++ src/gui_plugin/GnssWidgets/moc_PlotWidget.h (revision 5) @@ -0,0 +1,218 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'PlotWidget.h' +** +** Created by: The Qt Meta Object Compiler version 67 (Qt 5.7.0) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include +#include +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'PlotWidget.h' doesn't include ." +#elif Q_MOC_OUTPUT_REVISION != 67 +#error "This file was generated using the moc from 5.7.0. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +QT_BEGIN_MOC_NAMESPACE +struct qt_meta_stringdata_debugger__PlotWidget_t { + QByteArrayData data[8]; + char stringdata0[115]; +}; +#define QT_MOC_LITERAL(idx, ofs, len) \ + Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ + qptrdiff(offsetof(qt_meta_stringdata_debugger__PlotWidget_t, stringdata0) + ofs \ + - idx * sizeof(QByteArrayData)) \ + ) +static const qt_meta_stringdata_debugger__PlotWidget_t qt_meta_stringdata_debugger__PlotWidget = { + { +QT_MOC_LITERAL(0, 0, 20), // "debugger::PlotWidget" +QT_MOC_LITERAL(1, 21, 17), // "signalCmdResponse" +QT_MOC_LITERAL(2, 39, 0), // "" +QT_MOC_LITERAL(3, 40, 17), // "slotUpdateByTimer" +QT_MOC_LITERAL(4, 58, 15), // "slotCmdResponse" +QT_MOC_LITERAL(5, 74, 18), // "slotRightClickMenu" +QT_MOC_LITERAL(6, 93, 1), // "p" +QT_MOC_LITERAL(7, 95, 19) // "slotActionZoomClear" + + }, + "debugger::PlotWidget\0signalCmdResponse\0" + "\0slotUpdateByTimer\0slotCmdResponse\0" + "slotRightClickMenu\0p\0slotActionZoomClear" +}; +#undef QT_MOC_LITERAL + +static const uint qt_meta_data_debugger__PlotWidget[] = { + + // content: + 7, // revision + 0, // classname + 0, 0, // classinfo + 5, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 1, // signalCount + + // signals: name, argc, parameters, tag, flags + 1, 0, 39, 2, 0x06 /* Public */, + + // slots: name, argc, parameters, tag, flags + 3, 0, 40, 2, 0x0a /* Public */, + 4, 0, 41, 2, 0x0a /* Public */, + 5, 1, 42, 2, 0x0a /* Public */, + 7, 0, 45, 2, 0x0a /* Public */, + + // signals: parameters + QMetaType::Void, + + // slots: parameters + QMetaType::Void, + QMetaType::Void, + QMetaType::Void, QMetaType::QPoint, 6, + QMetaType::Void, + + 0 // eod +}; + +void debugger::PlotWidget::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) +{ + if (_c == QMetaObject::InvokeMetaMethod) { + PlotWidget *_t = static_cast(_o); + Q_UNUSED(_t) + switch (_id) { + case 0: _t->signalCmdResponse(); break; + case 1: _t->slotUpdateByTimer(); break; + case 2: _t->slotCmdResponse(); break; + case 3: _t->slotRightClickMenu((*reinterpret_cast< const QPoint(*)>(_a[1]))); break; + case 4: _t->slotActionZoomClear(); break; + default: ; + } + } else if (_c == QMetaObject::IndexOfMethod) { + int *result = reinterpret_cast(_a[0]); + void **func = reinterpret_cast(_a[1]); + { + typedef void (PlotWidget::*_t)(); + if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&PlotWidget::signalCmdResponse)) { + *result = 0; + return; + } + } + } +} + +const QMetaObject debugger::PlotWidget::staticMetaObject = { + { &QWidget::staticMetaObject, qt_meta_stringdata_debugger__PlotWidget.data, + qt_meta_data_debugger__PlotWidget, qt_static_metacall, Q_NULLPTR, Q_NULLPTR} +}; + + +const QMetaObject *debugger::PlotWidget::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject; +} + +void *debugger::PlotWidget::qt_metacast(const char *_clname) +{ + if (!_clname) return Q_NULLPTR; + if (!strcmp(_clname, qt_meta_stringdata_debugger__PlotWidget.stringdata0)) + return static_cast(const_cast< PlotWidget*>(this)); + if (!strcmp(_clname, "IGuiCmdHandler")) + return static_cast< IGuiCmdHandler*>(const_cast< PlotWidget*>(this)); + return QWidget::qt_metacast(_clname); +} + +int debugger::PlotWidget::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QWidget::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + if (_id < 5) + qt_static_metacall(this, _c, _id, _a); + _id -= 5; + } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) { + if (_id < 5) + *reinterpret_cast(_a[0]) = -1; + _id -= 5; + } + return _id; +} + +// SIGNAL 0 +void debugger::PlotWidget::signalCmdResponse() +{ + QMetaObject::activate(this, &staticMetaObject, 0, Q_NULLPTR); +} +struct qt_meta_stringdata_debugger__PlotQMdiSubWindow_t { + QByteArrayData data[1]; + char stringdata0[28]; +}; +#define QT_MOC_LITERAL(idx, ofs, len) \ + Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ + qptrdiff(offsetof(qt_meta_stringdata_debugger__PlotQMdiSubWindow_t, stringdata0) + ofs \ + - idx * sizeof(QByteArrayData)) \ + ) +static const qt_meta_stringdata_debugger__PlotQMdiSubWindow_t qt_meta_stringdata_debugger__PlotQMdiSubWindow = { + { +QT_MOC_LITERAL(0, 0, 27) // "debugger::PlotQMdiSubWindow" + + }, + "debugger::PlotQMdiSubWindow" +}; +#undef QT_MOC_LITERAL + +static const uint qt_meta_data_debugger__PlotQMdiSubWindow[] = { + + // content: + 7, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +void debugger::PlotQMdiSubWindow::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) +{ + Q_UNUSED(_o); + Q_UNUSED(_id); + Q_UNUSED(_c); + Q_UNUSED(_a); +} + +const QMetaObject debugger::PlotQMdiSubWindow::staticMetaObject = { + { &QMdiSubWindow::staticMetaObject, qt_meta_stringdata_debugger__PlotQMdiSubWindow.data, + qt_meta_data_debugger__PlotQMdiSubWindow, qt_static_metacall, Q_NULLPTR, Q_NULLPTR} +}; + + +const QMetaObject *debugger::PlotQMdiSubWindow::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject; +} + +void *debugger::PlotQMdiSubWindow::qt_metacast(const char *_clname) +{ + if (!_clname) return Q_NULLPTR; + if (!strcmp(_clname, qt_meta_stringdata_debugger__PlotQMdiSubWindow.stringdata0)) + return static_cast(const_cast< PlotQMdiSubWindow*>(this)); + return QMdiSubWindow::qt_metacast(_clname); +} + +int debugger::PlotQMdiSubWindow::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QMdiSubWindow::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} +QT_END_MOC_NAMESPACE
src/gui_plugin/GnssWidgets/moc_PlotWidget.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/gui_plugin/moc_qt_wrapper.h =================================================================== --- src/gui_plugin/moc_qt_wrapper.h (nonexistent) +++ src/gui_plugin/moc_qt_wrapper.h (revision 5) @@ -0,0 +1,135 @@ +/**************************************************************************** +** Meta object code from reading C++ file 'qt_wrapper.h' +** +** Created by: The Qt Meta Object Compiler version 67 (Qt 5.7.0) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include +#include +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'qt_wrapper.h' doesn't include ." +#elif Q_MOC_OUTPUT_REVISION != 67 +#error "This file was generated using the moc from 5.7.0. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +QT_BEGIN_MOC_NAMESPACE +struct qt_meta_stringdata_debugger__QtWrapper_t { + QByteArrayData data[4]; + char stringdata0[68]; +}; +#define QT_MOC_LITERAL(idx, ofs, len) \ + Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \ + qptrdiff(offsetof(qt_meta_stringdata_debugger__QtWrapper_t, stringdata0) + ofs \ + - idx * sizeof(QByteArrayData)) \ + ) +static const qt_meta_stringdata_debugger__QtWrapper_t qt_meta_stringdata_debugger__QtWrapper = { + { +QT_MOC_LITERAL(0, 0, 19), // "debugger::QtWrapper" +QT_MOC_LITERAL(1, 20, 19), // "signalPollingUpdate" +QT_MOC_LITERAL(2, 40, 0), // "" +QT_MOC_LITERAL(3, 41, 26) // "slotMainWindowAboutToClose" + + }, + "debugger::QtWrapper\0signalPollingUpdate\0" + "\0slotMainWindowAboutToClose" +}; +#undef QT_MOC_LITERAL + +static const uint qt_meta_data_debugger__QtWrapper[] = { + + // content: + 7, // revision + 0, // classname + 0, 0, // classinfo + 2, 14, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 1, // signalCount + + // signals: name, argc, parameters, tag, flags + 1, 0, 24, 2, 0x06 /* Public */, + + // slots: name, argc, parameters, tag, flags + 3, 0, 25, 2, 0x08 /* Private */, + + // signals: parameters + QMetaType::Void, + + // slots: parameters + QMetaType::Void, + + 0 // eod +}; + +void debugger::QtWrapper::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a) +{ + if (_c == QMetaObject::InvokeMetaMethod) { + QtWrapper *_t = static_cast(_o); + Q_UNUSED(_t) + switch (_id) { + case 0: _t->signalPollingUpdate(); break; + case 1: _t->slotMainWindowAboutToClose(); break; + default: ; + } + } else if (_c == QMetaObject::IndexOfMethod) { + int *result = reinterpret_cast(_a[0]); + void **func = reinterpret_cast(_a[1]); + { + typedef void (QtWrapper::*_t)(); + if (*reinterpret_cast<_t *>(func) == static_cast<_t>(&QtWrapper::signalPollingUpdate)) { + *result = 0; + return; + } + } + } + Q_UNUSED(_a); +} + +const QMetaObject debugger::QtWrapper::staticMetaObject = { + { &QObject::staticMetaObject, qt_meta_stringdata_debugger__QtWrapper.data, + qt_meta_data_debugger__QtWrapper, qt_static_metacall, Q_NULLPTR, Q_NULLPTR} +}; + + +const QMetaObject *debugger::QtWrapper::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject; +} + +void *debugger::QtWrapper::qt_metacast(const char *_clname) +{ + if (!_clname) return Q_NULLPTR; + if (!strcmp(_clname, qt_meta_stringdata_debugger__QtWrapper.stringdata0)) + return static_cast(const_cast< QtWrapper*>(this)); + return QObject::qt_metacast(_clname); +} + +int debugger::QtWrapper::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QObject::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + if (_c == QMetaObject::InvokeMetaMethod) { + if (_id < 2) + qt_static_metacall(this, _c, _id, _a); + _id -= 2; + } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) { + if (_id < 2) + *reinterpret_cast(_a[0]) = -1; + _id -= 2; + } + return _id; +} + +// SIGNAL 0 +void debugger::QtWrapper::signalPollingUpdate() +{ + QMetaObject::activate(this, &staticMetaObject, 0, Q_NULLPTR); +} +QT_END_MOC_NAMESPACE
src/gui_plugin/moc_qt_wrapper.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/gui_plugin/resources/gui.rcc =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: src/gui_plugin/resources/gui.rcc =================================================================== --- src/gui_plugin/resources/gui.rcc (nonexistent) +++ src/gui_plugin/resources/gui.rcc (revision 5)
src/gui_plugin/resources/gui.rcc Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: src/gui_plugin/resources/images/plot_96x96.png =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: src/gui_plugin/resources/images/plot_96x96.png =================================================================== --- src/gui_plugin/resources/images/plot_96x96.png (nonexistent) +++ src/gui_plugin/resources/images/plot_96x96.png (revision 5)
src/gui_plugin/resources/images/plot_96x96.png Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property Index: src/libdbg64g/services/.gitignore =================================================================== --- src/libdbg64g/services/.gitignore (nonexistent) +++ src/libdbg64g/services/.gitignore (revision 5) @@ -0,0 +1 @@ +!debug \ No newline at end of file Index: src/libdbg64g/services/debug/edcl.cpp =================================================================== --- src/libdbg64g/services/debug/edcl.cpp (nonexistent) +++ src/libdbg64g/services/debug/edcl.cpp (revision 5) @@ -0,0 +1,218 @@ +/** + * @file + * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Access to a hardware via Ethernet EDCL interface implementaion. + */ + +#include "edcl_types.h" +#include "edcl.h" + +namespace debugger { + +/** Class registration in the Core */ +REGISTER_CLASS(EdclService) + +EdclService::EdclService(const char *name) : IService(name) { + registerInterface(static_cast(this)); + registerAttribute("Transport", &transport_); + registerAttribute("seq_cnt", &seq_cnt_); + seq_cnt_.make_uint64(0); + itransport_ = 0; + + dbgRdTRansactionCnt_ = 0; +} + +void EdclService::postinitService() { + IService *iserv = + static_cast(RISCV_get_service(transport_.to_string())); + if (!iserv) { + RISCV_error("Transport service '%'s not found", + transport_.to_string()); + } + itransport_ = static_cast(iserv->getInterface(IFACE_LINK)); + if (!itransport_) { + RISCV_error("UDP interface '%s' not found", + transport_.to_string()); + } +} + +int EdclService::read(uint64_t addr, int bytes, uint8_t *obuf) { + int txoff, rxoff; + UdpEdclCommonType req = {0}; + UdpEdclCommonType rsp; + + if (!itransport_) { + RISCV_error("UDP transport not defined, addr=%x", addr); + return TAP_ERROR; + } + + int rd_bytes = 0; + while (rd_bytes < bytes && rd_bytes != TAP_ERROR) { + req.control.request.seqidx = + static_cast(seq_cnt_.to_uint64()); + req.control.request.write = 0; + req.address = static_cast(addr + rd_bytes); + if ((bytes - rd_bytes) > EDCL_PAYLOAD_MAX_BYTES) { + req.control.request.len = + static_cast(EDCL_PAYLOAD_MAX_BYTES); + } else { + req.control.request.len = static_cast(bytes - rd_bytes); + } + + txoff = write16(tx_buf_, 0, req.offset); + txoff = write32(tx_buf_, txoff, req.control.word); + txoff = write32(tx_buf_, txoff, req.address); + + txoff = itransport_->sendData(tx_buf_, txoff); + if (txoff == -1) { + RISCV_error("Data sending error", NULL); + rd_bytes = TAP_ERROR; + break; + } + + dbgRdTRansactionCnt_++; + rxoff = itransport_->readData(rx_buf_, sizeof(rx_buf_)); + if (rxoff == -1) { + RISCV_error("Data receiving error", NULL); + rd_bytes = TAP_ERROR; + break; + } + if (rxoff == 0) { + RISCV_error("No response. Break read transaction[%d] at %08x", + dbgRdTRansactionCnt_, req.address); + rd_bytes = TAP_ERROR; + break; + } + + rsp.control.word = read32(&rx_buf_[2]); + + const char *NAK[2] = {"ACK", "NAK"}; + RISCV_debug("EDCL read: %s[%d], len = %d", + NAK[rsp.control.response.nak], + rsp.control.response.seqidx, + rsp.control.response.len); + + // Retry with new sequence counter. + if (rsp.control.response.nak) { + RISCV_info("Sequence counter detected %d. Re-sending transaction.", + rsp.control.response.seqidx); + seq_cnt_.make_uint64(rsp.control.response.seqidx); + continue; + } + + // Try to receive next packet: + if (rsp.control.response.seqidx != seq_cnt_.to_uint32()) { + RISCV_error("Wrong ID received %d != %d. Try again.", + seq_cnt_.to_uint32(), rsp.control.response.seqidx); + + rxoff = itransport_->readData(rx_buf_, sizeof(rx_buf_)); + if (rxoff <= 0) { + rd_bytes = TAP_ERROR; + break; + } + rsp.control.word = read32(&rx_buf_[2]); + if (rsp.control.response.seqidx != seq_cnt_.to_uint32()) { + rd_bytes = TAP_ERROR; + break; + } + } + + memcpy(&obuf[rd_bytes], &rx_buf_[10], rsp.control.response.len); + rd_bytes += rsp.control.response.len; + seq_cnt_.make_uint64((seq_cnt_.to_uint64() + 1) & 0x3FFF); + } + return rd_bytes; +} + +int EdclService::write(uint64_t addr, int bytes, uint8_t *ibuf) { + int off; + UdpEdclCommonType req = {0}; + UdpEdclCommonType rsp; + + if (!itransport_) { + RISCV_error("UDP transport not defined, addr=%x", addr); + return TAP_ERROR; + } + + int wr_bytes = 0; + while (wr_bytes < bytes && wr_bytes != -1) { + req.control.request.seqidx = + static_cast(seq_cnt_.to_uint64()); + req.control.request.write = 1; + req.address = static_cast(addr + wr_bytes); + if ((bytes - wr_bytes) > EDCL_PAYLOAD_MAX_BYTES) { + req.control.request.len = + static_cast(EDCL_PAYLOAD_MAX_BYTES); + } else { + req.control.request.len = static_cast(bytes - wr_bytes); + } + + off = write16(tx_buf_, 0, req.offset); + off = write32(tx_buf_, off, req.control.word); + off = write32(tx_buf_, off, req.address); + memcpy(&tx_buf_[off], &ibuf[wr_bytes], req.control.request.len); + + + off = itransport_->sendData(tx_buf_, off + req.control.request.len); + if (off == -1) { + RISCV_error("Data sending error", NULL); + wr_bytes = -1; + break; + } + + off = itransport_->readData(rx_buf_, sizeof(rx_buf_)); + if (off == -1) { + RISCV_error("Data receiving error", NULL); + wr_bytes = -1; + break; + } + if (off == 0) { + RISCV_error("No response. Break write transaction.", NULL); + wr_bytes = -1; + break; + } + + rsp.control.word = read32(&rx_buf_[2]); + + // Warning: + // response length = 0; + const char *NAK[2] = {"ACK", "NAK"}; + RISCV_debug("EDCL write: %s[%d], len = %d", + NAK[rsp.control.response.nak], + rsp.control.response.seqidx, + req.control.request.len); + + // Retry with new sequence counter. + if (rsp.control.response.nak) { + RISCV_info("Sequence counter detected %d. Re-sending transaction.", + rsp.control.response.seqidx); + seq_cnt_.make_uint64(rsp.control.response.seqidx); + continue; + } + + wr_bytes += req.control.request.len; + seq_cnt_.make_uint64(seq_cnt_.to_uint64() + 1); + } + return wr_bytes; +} + +int EdclService::write16(uint8_t *buf, int off, uint16_t v) { + buf[off++] = (uint8_t)((v >> 8) & 0xFF); + buf[off++] = (uint8_t)(v & 0xFF); + return off; +} + +int EdclService::write32(uint8_t *buf, int off, uint32_t v) { + buf[off++] = (uint8_t)((v >> 24) & 0xFF); + buf[off++] = (uint8_t)((v >> 16) & 0xFF); + buf[off++] = (uint8_t)((v >> 8) & 0xFF); + buf[off++] = (uint8_t)(v & 0xFF); + return off; +} + +uint32_t EdclService::read32(uint8_t *buf) { + return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | (buf[3] << 0); +} + +} // namespace debugger
src/libdbg64g/services/debug/edcl.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/libdbg64g/services/debug/edcl.h =================================================================== --- src/libdbg64g/services/debug/edcl.h (nonexistent) +++ src/libdbg64g/services/debug/edcl.h (revision 5) @@ -0,0 +1,55 @@ +/** + * @file + * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Access to a hardware via Ethernet EDCL interface implementaion. + */ + +#ifndef __DEBUGGER_EDCL_H__ +#define __DEBUGGER_EDCL_H__ + +#include "iclass.h" +#include "iservice.h" +#include "coreservices/itap.h" +#include "coreservices/ilink.h" +#include + +namespace debugger { + +class EdclService : public IService, + public ITap { +public: + EdclService(const char *name); + + /** IService interface */ + virtual void postinitService(); + + /** ITap interface */ + virtual int read(uint64_t addr, int bytes, uint8_t *obuf); + virtual int write(uint64_t addr, int bytes, uint8_t *ibuf); + +private: + int write16(uint8_t *buf, int off, uint16_t v); + int write32(uint8_t *buf, int off, uint32_t v); + uint32_t read32(uint8_t *buf); + +private: + /** This is limitation of the MAC fifo. Protocol allows increase the + * following value up to 242 words. */ + static const int EDCL_PAYLOAD_MAX_WORDS32 = 8; + static const int EDCL_PAYLOAD_MAX_BYTES = 4*EDCL_PAYLOAD_MAX_WORDS32; + + uint8_t tx_buf_[4096]; + uint8_t rx_buf_[4096]; + ILink *itransport_; + AttributeType transport_; + AttributeType seq_cnt_; + + int dbgRdTRansactionCnt_; +}; + +DECLARE_CLASS(EdclService) + +} // namespace debugger + +#endif // __DEBUGGER_EDCL_H__
src/libdbg64g/services/debug/edcl.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/libdbg64g/services/debug/edcl_types.h =================================================================== --- src/libdbg64g/services/debug/edcl_types.h (nonexistent) +++ src/libdbg64g/services/debug/edcl_types.h (revision 5) @@ -0,0 +1,49 @@ +/** + * @file + * @copyright Copyright 2016 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief EDCL user defined transport structure. + */ + + #ifndef __DEBUGGER_EDCL_TYPES_H__ + #define __DEBUGGER_EDCL_TYPES_H__ + + #include + + namespace debugger { + +struct EdclControlRequestType { + // 32 bits fields: + uint32_t unused : 7; + uint32_t len : 10; + uint32_t write : 1; // read = 0; write = 1 + uint32_t seqidx : 14; // sequence id + //uint32 data; // 0 to 242 words +}; + + +struct EdclControlResponseType { + // 32 bits fields: + uint32_t unused : 7; + uint32_t len : 10; + uint32_t nak : 1; // ACK = 0; NAK = 1 + uint32_t seqidx : 14; // sequence id + //uint32 data; // 0 to 242 words +}; + +#pragma pack(1) +struct UdpEdclCommonType { + uint16_t offset; + union ControlType { + uint32_t word; + EdclControlRequestType request; + EdclControlResponseType response; + } control; + uint32_t address; + //uint32 data; // 0 to 242 words +}; +#pragma pack() + +} // namespace debugger + +#endif // __DEBUGGER_EDCL_TYPES_H__
src/libdbg64g/services/debug/edcl_types.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/libdbg64g/services/debug/serial_dbglink.cpp =================================================================== --- src/libdbg64g/services/debug/serial_dbglink.cpp (nonexistent) +++ src/libdbg64g/services/debug/serial_dbglink.cpp (revision 5) @@ -0,0 +1,165 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @details + * Write command: + * Send [11.Length-1].Addr[63:0].Data[31:0]*(x Length) + * Read command: + * Send [10.Length-1].Addr[63:0] + * Receive Data[31:0]*(x Length) + */ + +#include "api_core.h" +#include "serial_dbglink.h" + +namespace debugger { + +/** Class registration in the Core */ +REGISTER_CLASS(SerialDbgService) + +SerialDbgService::SerialDbgService(const char *name) + : IService(name) { + registerInterface(static_cast(this)); + registerAttribute("Timeout", &timeout_); + registerAttribute("Port", &port_); + + RISCV_event_create(&event_block_, "SerialDbg_event_block"); +} + +SerialDbgService::~SerialDbgService() { + RISCV_event_close(&event_block_); +} + +void SerialDbgService::postinitService() { + iserial_ = static_cast( + RISCV_get_service_iface(port_.to_string(), IFACE_SERIAL)); + if (!iserial_) { + RISCV_error("Can't find ISerial interface %s", port_.to_string()); + return; + } + iserial_->registerRawListener(static_cast(this)); +#if 1 // hardcoded scale in tapuart, no need in clock detection + /** Automatic baudrate definition on hardware side: + * [0] 0x55 - to init baud rate detector + * [1] 0x55 - to confirm baud rate value. + */ + char tbuf[5] = {0x55, 0x55, 0x55, 0x55}; + iserial_->writeData(tbuf, 4); +#endif +} + +void SerialDbgService::predeleteService() { + if (iserial_) { + iserial_->unregisterRawListener(static_cast(this)); + } +} + +int SerialDbgService::read(uint64_t addr, int bytes, uint8_t *obuf) { + if (!iserial_) { + return TAP_ERROR; + } + if (bytes <= 0 || (bytes & 0x3) != 0) { + RISCV_error("Unaligned read %d", bytes); + return TAP_ERROR; + } + addr &= 0xFFFFFFFFull; + int bytes_to_read = bytes; + uint8_t *tout = obuf; + pkt_.fields.magic = MAGIC_ID; + pkt_.fields.addr = addr; + while (bytes_to_read) { + pkt_.fields.cmd = (0x2 << 6); + if (bytes_to_read > 4 * UART_MST_BURST_MAX) { + req_count_ = 4 * UART_MST_BURST_MAX; + pkt_.fields.cmd |= 0x3F; + } else { + req_count_ = bytes_to_read; + pkt_.fields.cmd |= ((bytes_to_read / 4) - 1) & 0x3F; + } + rd_count_ = 0; + wait_bytes_ = req_count_; + RISCV_event_clear(&event_block_); + iserial_->writeData(pkt_.buf, UART_REQ_HEADER_SZ); + + if (RISCV_event_wait_ms(&event_block_, timeout_.to_int()) != 0) { + RISCV_error("Reading [%08" RV_PRI64 "x] failed", addr); + return TAP_ERROR; + } + if (rd_count_ != req_count_) { + RISCV_error("Read bytes %d of %d", rd_count_, req_count_); + return TAP_ERROR; + } + + memcpy(tout, rxbuf_[0].buf, rd_count_); + tout += rd_count_; + pkt_.fields.addr += static_cast(rd_count_); + bytes_to_read -= rd_count_; + } + return bytes; +} + +int SerialDbgService::write(uint64_t addr, int bytes, uint8_t *ibuf) { + if (!iserial_) { + return TAP_ERROR; + } + if (bytes <= 0 || (bytes & 0x3) != 0) { + RISCV_error("Unaligned write %d", bytes); + return TAP_ERROR; + } + addr &= 0xFFFFFFFFull; + int bytes_to_write = bytes; + uint8_t *tin = ibuf; + pkt_.fields.magic = MAGIC_ID; + pkt_.fields.addr = addr; + while (bytes_to_write) { + pkt_.fields.cmd = (0x3 << 6); + if (bytes_to_write > 4 * UART_MST_BURST_MAX) { + req_count_ = 4 * UART_MST_BURST_MAX; + pkt_.fields.cmd |= 0x3F; + } else { + req_count_ = bytes_to_write; + pkt_.fields.cmd |= ((bytes_to_write / 4) - 1) & 0x3F; + } + memcpy(pkt_.fields.data, tin, req_count_); + + wait_bytes_ = 4; + rd_count_ = 0; + RISCV_event_clear(&event_block_); + iserial_->writeData(pkt_.buf, UART_REQ_HEADER_SZ + req_count_); + + // Waiting "ACK\n" handshake + if (RISCV_event_wait_ms(&event_block_, timeout_.to_int()) != 0) { + RISCV_error("Writing [%08" RV_PRI64 "x] failed", addr); + return TAP_ERROR; + } + + tin += req_count_; + bytes_to_write -= req_count_; + pkt_.fields.addr += static_cast(req_count_); + } + return bytes; +} + +void SerialDbgService::updateData(const char *buf, int buflen) { + uint8_t *tbuf = &rxbuf_[0].buf[rd_count_]; + memcpy(tbuf, buf, buflen); + rd_count_ += buflen; + if (rd_count_ < wait_bytes_) { + return; + } + RISCV_event_set(&event_block_); +} + +} // namespace debugger
src/libdbg64g/services/debug/serial_dbglink.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/libdbg64g/services/debug/serial_dbglink.h =================================================================== --- src/libdbg64g/services/debug/serial_dbglink.h (nonexistent) +++ src/libdbg64g/services/debug/serial_dbglink.h (revision 5) @@ -0,0 +1,81 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEBUGGER_SERIAL_DBGLINK_SERVICE_H__ +#define __DEBUGGER_SERIAL_DBGLINK_SERVICE_H__ + +#include "iclass.h" +#include "iservice.h" +#include "coreservices/itap.h" +#include "coreservices/iserial.h" +#include "coreservices/irawlistener.h" + +namespace debugger { + +#define MAGIC_ID 0x31 +static const int UART_REQ_HEADER_SZ = 10; +static const int UART_MST_BURST_MAX = 64; + +#pragma pack(1) +struct UartMstPacketType { + uint8_t magic; + uint8_t cmd; + uint64_t addr; + uint32_t data[UART_MST_BURST_MAX]; +}; +#pragma pack() + +union PacketType { + UartMstPacketType fields; + char buf[1]; +}; + +class SerialDbgService : public IService, + public ITap, + public IRawListener { +public: + SerialDbgService(const char *name); + ~SerialDbgService(); + + /** IService interface */ + virtual void postinitService(); + virtual void predeleteService(); + + /** ITap interface */ + virtual int read(uint64_t addr, int bytes, uint8_t *obuf); + virtual int write(uint64_t addr, int bytes, uint8_t *ibuf); + + /** IRawListener interface */ + virtual void updateData(const char *buf, int buflen); + +private: + AttributeType timeout_; + AttributeType port_; + + ISerial *iserial_; + event_def event_block_; + PacketType pkt_; + int rd_count_; + int req_count_; + int wait_bytes_; + Reg64Type rxbuf_[UART_MST_BURST_MAX]; +}; + +DECLARE_CLASS(SerialDbgService) + +} // namespace debugger + +#endif // __DEBUGGER_SERIAL_DBGLINK_SERVICE_H__
src/libdbg64g/services/debug/serial_dbglink.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/libdbg64g/services/debug/udp_dbglink.cpp =================================================================== --- src/libdbg64g/services/debug/udp_dbglink.cpp (nonexistent) +++ src/libdbg64g/services/debug/udp_dbglink.cpp (revision 5) @@ -0,0 +1,259 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief UDP transport level implementation. + */ + +#include "api_core.h" +#include "udp_dbglink.h" + +namespace debugger { + +/** Class registration in the Core */ +REGISTER_CLASS(UdpService) + +UdpService::UdpService(const char *name) + : IService(name) { + registerInterface(static_cast(this)); + registerAttribute("Timeout", &timeout_); + registerAttribute("BlockingMode", &blockmode_); + registerAttribute("HostIP", &hostIP_); + registerAttribute("BoardIP", &boardIP_); + + timeout_.make_int64(0); + blockmode_.make_boolean(true); + hostIP_.make_string("192.168.0.53"); + boardIP_.make_string("192.168.0.51"); +} + +UdpService::~UdpService() { + closeDatagramSocket(); +} + +void UdpService::postinitService() { + createDatagramSocket(); + // define hardcoded remote address: + remote_sockaddr_ipv4_ = sockaddr_ipv4_; + remote_sockaddr_ipv4_.sin_addr.s_addr = inet_addr(boardIP_.to_string()); + + if (timeout_.to_int64()) { + struct timeval tv; +#if defined(_WIN32) || defined(__CYGWIN__) + /** On windows timeout of the setsockopt() function is the DWORD + * size variable in msec, so we use only the first field in timeval + * struct and directly assgign argument. + */ + tv.tv_usec = 0; + tv.tv_sec = static_cast(timeout_.to_int64()); +#else + tv.tv_usec = (timeout_.to_int64() % 1000) * 1000; + tv.tv_sec = static_cast(timeout_.to_int64()/1000); +#endif + + setsockopt(hsock_, SOL_SOCKET, SO_RCVTIMEO, + (char *)&tv, sizeof(struct timeval)); + } + + /** By default socket was created with Blocking mode */ + if (!blockmode_.to_bool()) { + setBlockingMode(false); + } +} + +int UdpService::createDatagramSocket() { + char hostName[256]; + if (gethostname(hostName, sizeof(hostName)) < 0) { + return -1; + } + + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + /** + * Check availability of IPv4 address assigned via attribute 'hostIP'. + * If it woudn't be found use the last avaialble IP address. + */ + bool host_ip_found = false; + int retval; + struct addrinfo *result = NULL; + struct addrinfo *ptr = NULL; + retval = getaddrinfo(hostName, "0", &hints, &result); + if (retval != 0) { + return -1; + } + + for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { + // Find only IPV4 address, ignore others. + if (ptr->ai_family != AF_INET) { + continue; + } + sockaddr_ipv4_ = *((struct sockaddr_in *)ptr->ai_addr); + RISCV_sprintf(sockaddr_ipv4_str_, sizeof(sockaddr_ipv4_str_), + "%s", inet_ntoa(sockaddr_ipv4_.sin_addr)); + + if (strcmp(inet_ntoa(sockaddr_ipv4_.sin_addr), + hostIP_.to_string()) == 0) { + host_ip_found = true; + break; + } + } + + if (!host_ip_found) { + RISCV_info("Selected IPv4 %s", inet_ntoa(sockaddr_ipv4_.sin_addr)); + } else { +#if 1 + /** jrkk proposal to hardcode IP address in a such way. No difference. */ + memset(&sockaddr_ipv4_, 0, sizeof (sockaddr_ipv4_)); + sockaddr_ipv4_.sin_family = AF_INET; + inet_pton(AF_INET, hostIP_.to_string(), &(sockaddr_ipv4_.sin_addr)); +#endif + } + + hsock_ = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (hsock_ < 0) { + RISCV_error("%s", "Error: socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)"); + return -1; + } + + int res = bind(hsock_, (struct sockaddr *)&sockaddr_ipv4_, + sizeof(sockaddr_ipv4_)); + if (res != 0) { + RISCV_error("Error: bind(hsock_, \"%s\", ...)", hostIP_.to_string()); + return -1; + } + + addr_size_t addr_sz = sizeof(sockaddr_ipv4_); + res = getsockname(hsock_, (struct sockaddr *)&sockaddr_ipv4_, &addr_sz); + sockaddr_ipv4_port_ = ntohs(sockaddr_ipv4_.sin_port); + + RISCV_info("\tIPv4 address %s:%d . . . opened", + sockaddr_ipv4_str_, sockaddr_ipv4_port_); + + return 0; +} + +void UdpService::closeDatagramSocket() { + if (hsock_ < 0) + return; + +#if defined(_WIN32) || defined(__CYGWIN__) + closesocket(hsock_); +#else + shutdown(hsock_, SHUT_RDWR); + close(hsock_); +#endif + hsock_ = -1; +} + +void UdpService::getConnectionSettings(AttributeType *settings) { + settings->make_dict(); + (*settings)["IP"] = AttributeType(inet_ntoa(sockaddr_ipv4_.sin_addr)); + (*settings)["Port"] = AttributeType(Attr_UInteger, + static_cast(sockaddr_ipv4_.sin_port)); +} + +void UdpService::setConnectionSettings(const AttributeType *target) { + if (!target->is_dict()) { + return; + } + remote_sockaddr_ipv4_.sin_addr.s_addr = + inet_addr((*target)["IP"].to_string()); + remote_sockaddr_ipv4_.sin_port = + static_cast((*target)["Port"].to_uint64()); +} + +bool UdpService::setBlockingMode(bool mode) { + int ret; +#if defined(_WIN32) || defined(__CYGWIN__) + u_long arg = mode ? 0 : 1; + ret = ioctlsocket(hsock_, FIONBIO, &arg); +#else + int flags = fcntl(hsock_, F_GETFL, 0); + if (flags < 0) { + return false; + } + flags = mode ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); + ret = fcntl(hsock_, F_SETFL, flags); +#endif + if (ret == 0) { + // success + blockmode_.make_boolean(mode); + return true; + } + return false; +} + +int UdpService::sendData(const uint8_t *msg, int len) { + int tx_bytes = sendto(hsock_, reinterpret_cast(msg), len, 0, + reinterpret_cast(&remote_sockaddr_ipv4_), + static_cast(sizeof(remote_sockaddr_ipv4_))); + + if (tx_bytes < 0) { +#if defined(_WIN32) || defined(__CYGWIN__) + RISCV_error("sendto() failed with error: %d\n", WSAGetLastError()); +#else + RISCV_error("sendto() failed\n", NULL); +#endif + return 1; + } else if (logLevel_.to_int() >= LOG_DEBUG) { + char dbg[1024]; + int pos = RISCV_sprintf(dbg, sizeof(dbg), "send %d bytes to %s:%d: ", + tx_bytes, + inet_ntoa(remote_sockaddr_ipv4_.sin_addr), + ntohs(remote_sockaddr_ipv4_.sin_port)); + + if (tx_bytes < 64) { + for (int i = 0; i < len; i++) { + pos += RISCV_sprintf(&dbg[pos], sizeof(dbg) - pos, + "%02x", msg[i] & 0xFF); + } + } + RISCV_debug("%s", dbg); + } + return tx_bytes; +} + +int UdpService::readData(const uint8_t *buf, int maxlen) { + int sockerr; + addr_size_t sockerr_len = sizeof(sockerr); + addr_size_t addr_sz = sizeof(sockaddr_ipv4_); + + int res = recvfrom(hsock_, rcvbuf, sizeof(rcvbuf), + 0, (struct sockaddr *)&sockaddr_ipv4_, &addr_sz); + getsockopt(hsock_, SOL_SOCKET, SO_ERROR, + (char *)&sockerr, &sockerr_len); + + if (res < 0 && sockerr < 0) { + RISCV_error("Socket error %x", sockerr); + res = -1; + } else if (res < 0 && sockerr == 0) { + // Timeout: + res = 0; + } else if (res > 0) { + if (maxlen < res) { + res = maxlen; + RISCV_error("Receiver's buffer overflow maxlen = %d", maxlen); + } + memcpy(const_cast(buf), rcvbuf, res); + + if (logLevel_.to_int() >= LOG_DEBUG) { + char dbg[1024]; + int pos = RISCV_sprintf(dbg, sizeof(dbg), + "received %d Bytes: ", res); + if (res < 64) { + for (int i = 0; i < res; i++) { + pos += RISCV_sprintf(&dbg[pos], sizeof(dbg) - pos, + "%02x", rcvbuf[i] & 0xFF); + } + } + RISCV_debug("%s", dbg); + } + } + return res; +} + +} // namespace debugger
src/libdbg64g/services/debug/udp_dbglink.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/libdbg64g/services/debug/udp_dbglink.h =================================================================== --- src/libdbg64g/services/debug/udp_dbglink.h (nonexistent) +++ src/libdbg64g/services/debug/udp_dbglink.h (revision 5) @@ -0,0 +1,56 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief UDP transport level implementation. + */ + +#ifndef __DEBUGGER_UDP_DBGLINK_SERVICE_H__ +#define __DEBUGGER_UDP_DBGLINK_SERVICE_H__ + +#include "iclass.h" +#include "iservice.h" +#include "coreservices/ilink.h" +#include "coreservices/itap.h" + +namespace debugger { + +class UdpService : public IService, + public ILink { +public: + UdpService(const char *name); + ~UdpService(); + + /** IService interface */ + virtual void postinitService(); + + /** ILink interface */ + virtual void getConnectionSettings(AttributeType *settings); + virtual void setConnectionSettings(const AttributeType *target); + virtual int sendData(const uint8_t *msg, int len); + virtual int readData(const uint8_t *buf, int maxlen); + +protected: + int createDatagramSocket(); + void closeDatagramSocket(); + bool setBlockingMode(bool mode); + +private: + AttributeType timeout_; + AttributeType blockmode_; + AttributeType hostIP_; + AttributeType boardIP_; + + struct sockaddr_in sockaddr_ipv4_; + char sockaddr_ipv4_str_[16]; // 3 dots + 4 digits each 3 symbols + '\0' = 4*3 + 3 + 1; + unsigned short sockaddr_ipv4_port_; + struct sockaddr_in remote_sockaddr_ipv4_; + socket_def hsock_; + char rcvbuf[4096]; +}; + +DECLARE_CLASS(UdpService) + +} // namespace debugger + +#endif // __DEBUGGER_UDP_DBGLINK_SERVICE_H__
src/libdbg64g/services/debug/udp_dbglink.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/libdbg64g/services/exec/cmd/cmd_loadbin.cpp =================================================================== --- src/libdbg64g/services/exec/cmd/cmd_loadbin.cpp (nonexistent) +++ src/libdbg64g/services/exec/cmd/cmd_loadbin.cpp (revision 5) @@ -0,0 +1,67 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "iservice.h" +#include "cmd_loadbin.h" +#include + +namespace debugger { + +CmdLoadBin::CmdLoadBin(ITap *tap, ISocInfo *info) + : ICommand ("loadbin", tap, info) { + + briefDescr_.make_string("Load binary file"); + detailedDescr_.make_string( + "Description:\n" + " Load BIN-file to SOC target memory with specified address.\n" + "Example:\n" + " loadsrec /home/hc08/image.bin 0x04000\n"); +} + +bool CmdLoadBin::isValid(AttributeType *args) { + if ((*args)[0u].is_equal("loadbin") + && args->size() == 3) { + return CMD_VALID; + } + return CMD_INVALID; +} + +void CmdLoadBin::exec(AttributeType *args, AttributeType *res) { + res->make_nil(); + if (!isValid(args)) { + generateError(res, "Wrong argument list"); + return; + } + + const char *filename = (*args)[1].to_string(); + FILE *fp = fopen(filename, "rb"); + if (!fp) { + generateError(res, "File not found"); + return; + } + fseek(fp, 0, SEEK_END); + int sz = ftell(fp); + rewind(fp); + uint8_t *image = new uint8_t[sz]; + fread(image, 1, sz, fp); + fclose(fp); + + uint64_t addr = (*args)[2].to_uint64(); + tap_->write(addr, sz, image); + delete [] image; +} + +} // namespace debugger
src/libdbg64g/services/exec/cmd/cmd_loadbin.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/libdbg64g/services/exec/cmd/cmd_loadbin.h =================================================================== --- src/libdbg64g/services/exec/cmd/cmd_loadbin.h (nonexistent) +++ src/libdbg64g/services/exec/cmd/cmd_loadbin.h (revision 5) @@ -0,0 +1,30 @@ +/** + * @file + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Binary-file loader command. + */ + +#ifndef __DEBUGGER_SERVICES_EXEC_CMD_LOADBIN_H__ +#define __DEBUGGER_SERVICES_EXEC_CMD_LOADBIN_H__ + +#include "api_core.h" +#include "coreservices/itap.h" +#include "coreservices/isocinfo.h" +#include "coreservices/icommand.h" + +namespace debugger { + +class CmdLoadBin : public ICommand { + public: + explicit CmdLoadBin(ITap *tap, ISocInfo *info); + + /** ICommand interface */ + virtual bool isValid(AttributeType *args); + virtual void exec(AttributeType *args, AttributeType *res); + + private: +}; + +} // namespace debugger + +#endif // __DEBUGGER_SERVICES_EXEC_CMD_LOADBIN_H__
src/libdbg64g/services/exec/cmd/cmd_loadbin.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/libdbg64g/services/exec/cmd/cmd_loadsrec.cpp =================================================================== --- src/libdbg64g/services/exec/cmd/cmd_loadsrec.cpp (nonexistent) +++ src/libdbg64g/services/exec/cmd/cmd_loadsrec.cpp (revision 5) @@ -0,0 +1,252 @@ +/** + * @file + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief SREC-file loader command. + */ + +#include "iservice.h" +#include "cmd_loadsrec.h" +#include + +namespace debugger { + +//#define SHOW_USAGE_INFO + +#ifdef SHOW_USAGE_INFO +#define ADDR_SPACE (1 << 16) +char mark_[ADDR_SPACE] = {0}; + +void mark_addr(uint64_t addr, int len) { + for (int i = 0; i < len; i++) { + if ((addr + i) >= ADDR_SPACE) { + continue; + } + mark_[addr + i] = 1; + } +} + +bool is_flash(unsigned addr) { + if (addr >= 0x0450 && addr < 0x0500) { + return true; + } + if (addr >= 0x0580 && addr < 0x0600) { + return true; + } + if (addr >= 0x0E00 && addr < 0xfe00) { + return true; + } + return false; +} + +void print_flash_usage() { + unsigned start_addr = 0; + int cnt = 0; + int total_cnt = 0; + + RISCV_printf(NULL, 0, "!!! Free Flash regions:", NULL); + for (unsigned i = 0; i < ADDR_SPACE; i++) { + if (!is_flash(i)) { + if (cnt != 0) { + RISCV_printf(NULL, 0, " [%04x..%04x], length %d B", + start_addr, (start_addr + cnt - 1), cnt); + total_cnt += cnt; + cnt = 0; + } + continue; + } + + if (mark_[i]) { + if (cnt != 0) { + RISCV_printf(NULL, 0, " [%04x..%04x], length %d B", + start_addr, (start_addr + cnt - 1), cnt); + total_cnt += cnt; + cnt = 0; + } + continue; + } + if (cnt == 0) { + start_addr = i; + } + cnt++; + } + + RISCV_printf(NULL, 0, " =========================", NULL); + RISCV_printf(NULL, 0, " Total: %d B", total_cnt); +} +#endif + +CmdLoadSrec::CmdLoadSrec(ITap *tap, ISocInfo *info) + : ICommand ("loadsrec", tap, info) { + + briefDescr_.make_string("Load SREC-file"); + detailedDescr_.make_string( + "Description:\n" + " Load SREC-file to SOC target memory.\n" + "Example:\n" + " loadsrec /home/hc08/image.s19\n"); +} + +bool CmdLoadSrec::isValid(AttributeType *args) { + if ((*args)[0u].is_equal("loadsrec") + && (args->size() == 2 || args->size() == 3)) { + return CMD_VALID; + } + return CMD_INVALID; +} + +void CmdLoadSrec::exec(AttributeType *args, AttributeType *res) { + res->make_nil(); + if (!isValid(args)) { + generateError(res, "Wrong argument list"); + return; + } + + const char *filename = (*args)[1].to_string(); + FILE *fp = fopen(filename, "rb"); + if (!fp) { + generateError(res, "File not found"); + return; + } + fseek(fp, 0, SEEK_END); + int sz = ftell(fp); + rewind(fp); + uint8_t *image = new uint8_t[sz]; + fread(image, 1, sz, fp); + fclose(fp); + + int off = check_header(image); + + DsuMapType *dsu = info_->getpDsu(); + uint64_t soft_reset = 1; + uint64_t addr = reinterpret_cast(&dsu->ulocal.v.soft_reset); + tap_->write(addr, 8, reinterpret_cast(&soft_reset)); + + uint64_t sec_addr; + int sec_sz; + uint8_t sec_data[1024]; + while ((off = readline(image, off, sec_addr, sec_sz, sec_data)) != 0) { + tap_->write(sec_addr, sec_sz, sec_data); +#ifdef SHOW_USAGE_INFO + mark_addr(sec_addr, sec_sz); +#endif + } + +// soft_reset = 0; +// tap_->write(addr, 8, reinterpret_cast(&soft_reset)); + delete [] image; + +#ifdef SHOW_USAGE_INFO + print_flash_usage(); +#endif +} + +uint8_t CmdLoadSrec::str2byte(uint8_t *pair) { + uint8_t ret = 0; + for (int i = 0; i < 2; i++) { + ret <<= 4; + if (pair[i] >= '0' && pair[i] <= '9') { + ret |= pair[i] - '0'; + } else if (pair[i] >= 'A' && pair[i] <= 'F') { + ret |= pair[i] - 'A' + 10; + } else if (pair[i] >= 'a' && pair[i] <= 'f') { + ret |= pair[i] - 'a' + 10; + } + } + return ret; +} + +bool CmdLoadSrec::check_crc(uint8_t *str, int sz) { + uint8_t sum = 0; + uint8_t *cur = str; + for (int i = 0; i < sz; i++) { + sum += str2byte(cur); + cur += 2; + } + sum = ~sum; + uint8_t ctrl = str2byte(cur); + return ctrl == sum; +} + +int CmdLoadSrec::check_header(uint8_t *img) { + int off = 2; + if (img[0] != 'S' || img[1] != '0') { + return 0; + } + uint8_t sz = str2byte(&img[off]); + if (!check_crc(&img[off], sz)) { + return 0; + } + + off += 2; + uint16_t addr = str2byte(&img[off]); + off += 2; + addr = (addr << 8) + str2byte(&img[off]); + off += 2; + if (addr != 0) { + return 0; + } + for (int i = 0; i < sz - 3; i++) { // size (1) + addr (2) = 3 + header_data_[i] = static_cast(str2byte(&img[off])); + header_data_[i + 1] = 0; + off += 2; + } + off += 2; // skip checksum + if (img[off] != '\r' || img[off + 1] != '\n') { + return 0; + } + return off + 2; +} + +int CmdLoadSrec::readline(uint8_t *img, int off, + uint64_t &addr, int &sz, uint8_t *out) { + if (img[off++] != 'S') { + return 0; + } + int bytes4addr = 0; + switch (img[off++]) { // 16-bits address only + case '1': + bytes4addr = 2; // 16-bits address + break; + case '2': + bytes4addr = 3; // 24-bits address + break; + case '3': + bytes4addr = 4; // 32-bits address + break; + default: + return 0; + } + sz = str2byte(&img[off]); + if (!check_crc(&img[off], sz)) { + return 0; + } + sz -= 1; + off += 2; + + addr = 0; + for (int i = 0; i < bytes4addr; i++) { + addr <<= 8; + addr += str2byte(&img[off]); + off += 2; + sz--; + } +#if 1 + // MCU specific endcoding: + if (bytes4addr == 3) { + uint64_t page = addr >> 16; + addr = (0x4000 * page) + (addr & 0x3FFF); + } +#endif + + for (int i = 0; i < sz; i++) { + out[i] = static_cast(str2byte(&img[off])); + off += 2; + } + off += 2; // skip checksum + if (img[off] != '\r' || img[off + 1] != '\n') { + return 0; + } + return off + 2; +} + +} // namespace debugger
src/libdbg64g/services/exec/cmd/cmd_loadsrec.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/libdbg64g/services/exec/cmd/cmd_loadsrec.h =================================================================== --- src/libdbg64g/services/exec/cmd/cmd_loadsrec.h (nonexistent) +++ src/libdbg64g/services/exec/cmd/cmd_loadsrec.h (revision 5) @@ -0,0 +1,38 @@ +/** + * @file + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief SREC-file loader command. + */ + +#ifndef __DEBUGGER_CMD_LOADSREC_H__ +#define __DEBUGGER_CMD_LOADSREC_H__ + +#include "api_core.h" +#include "coreservices/itap.h" +#include "coreservices/isocinfo.h" +#include "coreservices/icommand.h" + +namespace debugger { + +class CmdLoadSrec : public ICommand { +public: + explicit CmdLoadSrec(ITap *tap, ISocInfo *info); + + /** ICommand interface */ + virtual bool isValid(AttributeType *args); + virtual void exec(AttributeType *args, AttributeType *res); + +private: + uint8_t str2byte(uint8_t *pair); + bool check_crc(uint8_t *str, int sz); + int check_header(uint8_t *img); + int readline(uint8_t *img, int off, + uint64_t &addr, int &sz, uint8_t *out); + +private: + char header_data_[1024]; +}; + +} // namespace debugger + +#endif // __DEBUGGER_CMD_LOADSREC_H__
src/libdbg64g/services/exec/cmd/cmd_loadsrec.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/libdbg64g/services/remote/tcpclient.cpp =================================================================== --- src/libdbg64g/services/remote/tcpclient.cpp (nonexistent) +++ src/libdbg64g/services/remote/tcpclient.cpp (revision 5) @@ -0,0 +1,126 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Remote access to debugger via TCP connection. Client thread. + */ + +#include "tcpclient.h" + +namespace debugger { + +/** Class registration in the Core */ +REGISTER_CLASS(TcpClient) + +TcpClient::TcpClient(const char *name) : IService(name), + tcpcmd_(static_cast(this)) { + registerInterface(static_cast(this)); + registerAttribute("Enable", &isEnable_); + RISCV_mutex_init(&mutexTx_); +} + +TcpClient::~TcpClient() { + RISCV_mutex_destroy(&mutexTx_); +} + +void TcpClient::postinitService() { + if (isEnable_.to_bool()) { + if (!run()) { + RISCV_error("Can't create thread.", NULL); + return; + } + } +} + +void TcpClient::updateData(const char *buf, int buflen) { + AttributeType console; + console.make_list(2); + console[0u].make_string("Console"); + console[1].make_string(buf); + console.to_config(); + + RISCV_mutex_lock(&mutexTx_); + memcpy(&txbuf_[txcnt_], console.to_string(), console.size() + 1); + txcnt_ += console.size() + 1; + RISCV_mutex_unlock(&mutexTx_); +} + +void TcpClient::busyLoop() { + int rxbytes; + int sockerr; + addr_size_t sockerr_len = sizeof(sockerr); + RISCV_add_default_output(static_cast(this)); + + cmdcnt_ = 0; + txcnt_ = 0; + while (isEnabled()) { + rxbytes = recv(hsock_, rcvbuf, sizeof(rcvbuf), 0); + getsockopt(hsock_, SOL_SOCKET, SO_ERROR, + reinterpret_cast(&sockerr), &sockerr_len); + + if (rxbytes == 0) { + RISCV_error("Socket error: rxbytes=%d, sockerr=%d", + rxbytes, sockerr); + loopEnable_.state = false; + } else if (rxbytes < 0) { + // Timeout: + } else if (rxbytes > 0) { + for (int i = 0; i < rxbytes; i++) { + cmdbuf_[cmdcnt_++] = rcvbuf[i]; + if (rcvbuf[i] == '\0') { + processRxString(); + cmdcnt_ = 0; + } + } + } + if (sendTxBuf() < 0) { + RISCV_error("Send error: txcnt=%d", txcnt_); + loopEnable_.state = false; + } + } + closeSocket(); + RISCV_remove_default_output(static_cast(this)); +} + +void TcpClient::processRxString() { + tcpcmd_.updateData(cmdbuf_, cmdcnt_); + AttributeType *resp = tcpcmd_.response(); + RISCV_mutex_lock(&mutexTx_); + memcpy(&txbuf_[txcnt_], resp->to_string(), resp->size() + 1); + txcnt_ += resp->size() + 1; + RISCV_mutex_unlock(&mutexTx_); +} + +int TcpClient::sendTxBuf() { + int total = txcnt_; + char *ptx = txbuf_; + int txbytes; + while (total > 0) { + txbytes = send(hsock_, ptx, total, 0); + if (txbytes == 0) { + return -1; + } + total -= txbytes; + ptx += txbytes; + } + RISCV_mutex_lock(&mutexTx_); + txcnt_ = 0; + RISCV_mutex_unlock(&mutexTx_); + return 0; +} + +void TcpClient::closeSocket() { + if (hsock_ < 0) { + return; + } + +#if defined(_WIN32) || defined(__CYGWIN__) + closesocket(hsock_); +#else + shutdown(hsock_, SHUT_RDWR); + close(hsock_); +#endif + hsock_ = -1; +} + +} // namespace debugger
src/libdbg64g/services/remote/tcpclient.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/libdbg64g/services/remote/tcpclient.h =================================================================== --- src/libdbg64g/services/remote/tcpclient.h (nonexistent) +++ src/libdbg64g/services/remote/tcpclient.h (revision 5) @@ -0,0 +1,62 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Remote access to debugger via TCP connection. Client thread. + */ + +#ifndef __DEBUGGER_TCPCLIENT_H__ +#define __DEBUGGER_TCPCLIENT_H__ + +#include +#include +#include "tcpcmd.h" +#include "coreservices/ithread.h" +#include "coreservices/irawlistener.h" + +namespace debugger { + +class TcpClient : public IService, + public IThread, + public IRawListener { + public: + explicit TcpClient(const char *name); + virtual ~TcpClient(); + + /** IService interface */ + virtual void postinitService(); + virtual void setExtArgument(void *args) { + hsock_ = *reinterpret_cast(args); + } + + /** IRawListener interface */ + virtual void updateData(const char *buf, int buflen); + + protected: + /** IThread interface */ + virtual void busyLoop(); + + protected: + void processRxString(); + int sendTxBuf(); + void closeSocket(); + + private: + AttributeType isEnable_; + AttributeType timeout_; + socket_def hsock_; + mutex_def mutexTx_; + char rcvbuf[4096]; + char cmdbuf_[4096]; + int cmdcnt_; + char txbuf_[1<<20]; + int txcnt_; + + TcpCommands tcpcmd_; +}; + +DECLARE_CLASS(TcpClient) + +} // namespace debugger + +#endif // __DEBUGGER_TCPCLIENT_H__
src/libdbg64g/services/remote/tcpclient.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/libdbg64g/services/remote/tcpcmd.cpp =================================================================== --- src/libdbg64g/services/remote/tcpcmd.cpp (nonexistent) +++ src/libdbg64g/services/remote/tcpcmd.cpp (revision 5) @@ -0,0 +1,310 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief TCP commands parser/processor. + */ + +#include "tcpcmd.h" + +namespace debugger { + +TcpCommands::TcpCommands(IService *parent) : IHap(HAP_All) { + parent_ = parent; + rxcnt_ = 0; + + cpu_.make_string("core0"); + executor_.make_string("cmdexec0"); + source_.make_string("src0"); + + iexec_ = static_cast( + RISCV_get_service_iface(executor_.to_string(), IFACE_CMD_EXECUTOR)); + + iclk_ = static_cast( + RISCV_get_service_iface(cpu_.to_string(), IFACE_CLOCK)); + IService *iservcpu = static_cast( + RISCV_get_service(cpu_.to_string())); + cpuLogLevel_ = static_cast( + iservcpu->getAttribute("LogLevel")); + + iriscv_ = static_cast( + RISCV_get_service_iface(cpu_.to_string(), IFACE_CPU_RISCV)); + + isrc_ = static_cast( + RISCV_get_service_iface(source_.to_string(), IFACE_SOURCE_CODE)); + + char tstr[128]; + RISCV_sprintf(tstr, sizeof(tstr), "%s_halt", parent_->getObjName()); + RISCV_event_create(&eventHalt_, tstr); + RISCV_sprintf(tstr, sizeof(tstr), "%s_delay_ms", parent_->getObjName()); + RISCV_event_create(&eventDelayMs_, tstr); + RISCV_sprintf(tstr, sizeof(tstr), "%s_pwr", parent_->getObjName()); + RISCV_event_create(&eventPowerChanged_, tstr); + + RISCV_register_hap(static_cast(this)); +} + +TcpCommands::~TcpCommands() { + RISCV_event_close(&eventHalt_); + RISCV_event_close(&eventDelayMs_); + RISCV_event_close(&eventPowerChanged_); +} + +void TcpCommands::hapTriggered(IFace *isrc, EHapType type, + const char *descr) { + if (type == HAP_Halt) { + RISCV_event_set(&eventHalt_); + } else if (type == HAP_CpuTurnON || type == HAP_CpuTurnOFF) { + RISCV_event_set(&eventPowerChanged_); + } +} + +void TcpCommands::stepCallback(uint64_t t) { + RISCV_event_set(&eventDelayMs_); +} + +void TcpCommands::updateData(const char *buf, int buflen) { + for (int i = 0; i < buflen; i++) { + rxbuf_[rxcnt_++] = buf[i]; + if (buf[i] == 0) { + processCommand(); + rxcnt_ = 0; + } + } +} + +void TcpCommands::processCommand() { + AttributeType cmd; + cmd.from_config(rxbuf_); + if (!cmd.is_list() || cmd.size() < 3) { + return; + } + + uint64_t idx = cmd[0u].to_uint64(); + resp_.make_list(2); + resp_[0u].make_uint64(idx); + resp_[1].make_string("OK"); + + AttributeType &requestType = cmd[1]; + AttributeType &requestAction = cmd[2]; + AttributeType *resp = &resp_[1]; + + if (requestType.is_equal("Command")) { + /** Redirect command to console directly */ + iexec_->exec(requestAction.to_string(), resp, false); + } else if (requestType.is_equal("Breakpoint")) { + /** Breakpoints action */ + if (requestAction[0u].is_equal("Add")) { + br_add(requestAction[1], resp); + } else if (requestAction[0u].is_equal("Remove")) { + br_rm(requestAction[1], resp); + } else { + resp->make_string("Wrong breakpoint command"); + } + } else if (requestType.is_equal("Control")) { + /** Run Control action */ + if (requestAction[0u].is_equal("GoUntil")) { + go_until(requestAction[1], resp); + } else if (requestAction[0u].is_equal("GoMsec")) { + go_msec(requestAction[1], resp); + } else if (requestAction[0u].is_equal("Step")) { + step(requestAction[1].to_int(), resp); + } else if (requestAction[0u].is_equal("PowerOn")) { + power_on(resp); + RISCV_debug("[%" RV_PRI64 "d] Command Power-On", idx); + } else if (requestAction[0u].is_equal("PowerOff")) { + power_off(resp); + RISCV_debug("[%" RV_PRI64 "d] Command Power-Off", idx); + } else { + resp->make_string("Wrong control command"); + } + } else if (requestType.is_equal("Status")) { + /** Pump status */ + if (requestAction.is_equal("IsON")) { + resp->make_boolean(true); + } else if (requestAction.is_equal("IsHalt")) { + //resp->make_boolean(iriscv_->isHalt()); + } else if (requestAction.is_equal("Steps")) { + resp->make_uint64(iclk_->getStepCounter()); + } else if (requestAction.is_equal("TimeSec")) { + double t1 = iclk_->getStepCounter() / iclk_->getFreqHz(); + resp->make_floating(t1); + } else { + resp->make_string("Wrong status command"); + } + } else if (requestType.is_equal("Symbol")) { + /** Symbols table conversion */ + if (requestAction[0u].is_equal("ToAddr")) { + symb2addr(requestAction[1].to_string(), resp); + } else if (requestAction[0u].is_equal("FromAddr")) { + // todo: + } else { + resp->make_string("Wrong symbol command"); + } + } else if (requestType.is_equal("Attribute")) { + IService *isrv = static_cast( + RISCV_get_service(requestAction[0u].to_string())); + if (isrv) { + AttributeType *iatr = static_cast( + isrv->getAttribute(requestAction[1].to_string())); + if (iatr) { + resp->clone(iatr); + } else { + resp->make_string("Attribute not found"); + } + } else { + resp->make_string("Service not found"); + } + } else { + resp->make_list(2); + (*resp)[0u].make_string("ERROR"); + (*resp)[1].make_string("Wrong command format"); + } + resp_.to_config(); +} + +AttributeType *TcpCommands::response() { + return &resp_; +} + +void TcpCommands::br_add(const AttributeType &symb, AttributeType *res) { + uint64_t addr; + if (symb.is_string()) { + AttributeType t1; + symb2addr(symb.to_string(), &t1); + if (t1.is_nil()) { + res->make_string("br_add: Symbol not found"); + return; + } + addr = t1.to_uint64(); + } else if (symb.is_integer()) { + addr = symb.to_uint64(); + } else { + res->make_string("br_add: Wrong format"); + return; + } + char tstr[256]; + RISCV_sprintf(tstr, sizeof(tstr), "br add 0x%x", addr); + iexec_->exec(tstr, res, false); +} + +void TcpCommands::br_rm(const AttributeType &symb, AttributeType *res) { + uint64_t addr; + if (symb.is_string()) { + AttributeType t1; + symb2addr(symb.to_string(), &t1); + if (t1.is_nil()) { + res->make_string("br_rm: Symbol not found"); + return; + } + addr = t1.to_uint64(); + } else if (symb.is_integer()) { + addr = symb.to_uint64(); + } else { + res->make_string("br_rm: Wrong format"); + return; + } + char tstr[256]; + RISCV_sprintf(tstr, sizeof(tstr), "br rm 0x%x", addr); + iexec_->exec(tstr, res, false); +} + +void TcpCommands::step(int cnt, AttributeType *res) { + char tstr[16]; + RISCV_sprintf(tstr, sizeof(tstr), "c %d", cnt); + + int log_level_old = cpuLogLevel_->to_int(); + cpuLogLevel_->make_int64(4); + + RISCV_event_clear(&eventHalt_); + iexec_->exec(tstr, res, false); + RISCV_event_wait(&eventHalt_); + cpuLogLevel_->make_int64(log_level_old); +} + +void TcpCommands::go_until(const AttributeType &symb, AttributeType *res) { + uint64_t addr; + if (symb.is_string()) { + AttributeType t1; + symb2addr(symb.to_string(), &t1); + if (t1.is_nil()) { + res->make_string("br_rm: Symbol not found"); + return; + } + addr = t1.to_uint64(); + } else if (symb.is_integer()) { + addr = symb.to_uint64(); + } else { + res->make_string("br_rm: Wrong format"); + return; + } + // Add breakpoint + char tstr[256]; + RISCV_sprintf(tstr, sizeof(tstr), "br add 0x%x", addr); + iexec_->exec(tstr, res, false); + + // Set CPU LogLevel=1 to hide all debugging messages + int log_level_old = cpuLogLevel_->to_int(); + cpuLogLevel_->make_int64(1); + + // Run simulation + RISCV_event_clear(&eventHalt_); + RISCV_sprintf(tstr, sizeof(tstr), "c", 0); + iexec_->exec(tstr, res, false); + RISCV_event_wait(&eventHalt_); + cpuLogLevel_->make_int64(log_level_old); + + // Remove breakpoint: + RISCV_sprintf(tstr, sizeof(tstr), "br rm 0x%x", addr); + iexec_->exec(tstr, res, false); +} + +void TcpCommands::symb2addr(const char *symbol, AttributeType *res) { + res->make_nil(); + if (!isrc_) { + return; + } + // Letters capitalization: + char capital[256]; + int i = 0; + while (symbol[i]) { + capital[i] = symbol[i]; + if (symbol[i] >= 'a' && symbol[i] <= 'z') { + capital[i] += ('A' - 'a'); + } + i++; + capital[i] = '\0'; + } + uint64_t addr; + if (isrc_->symbol2Address(capital, &addr) == 0) { + res->make_uint64(addr); + return; + } +} + +void TcpCommands::power_on(AttributeType *res) { +} + +void TcpCommands::power_off(AttributeType *res) { +} + +void TcpCommands::go_msec(const AttributeType &msec, AttributeType *res) { + RISCV_event_clear(&eventDelayMs_); + RISCV_event_clear(&eventHalt_); + + uint64_t step = iclk_->getStepCounter(); + double delta = 0.001 * iclk_->getFreqHz() * msec.to_float(); + if (delta == 0) { + delta = 1; + } + iclk_->registerStepCallback(static_cast(this), + step + static_cast(delta)); + + iexec_->exec("c", res, false); + RISCV_event_wait(&eventDelayMs_); + iexec_->exec("s", res, false); + RISCV_event_wait(&eventHalt_); +} + + +} // namespace debugger
src/libdbg64g/services/remote/tcpcmd.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/libdbg64g/services/remote/tcpcmd.h =================================================================== --- src/libdbg64g/services/remote/tcpcmd.h (nonexistent) +++ src/libdbg64g/services/remote/tcpcmd.h (revision 5) @@ -0,0 +1,85 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief TCP commands parser/processor. + */ + +#ifndef __DEBUGGER_TCPCMD_H__ +#define __DEBUGGER_TCPCMD_H__ + +#include +#include +#include +#include +#include "coreservices/ilink.h" +#include "coreservices/ithread.h" +#include "coreservices/icpugen.h" +#include "coreservices/icpuriscv.h" +#include "coreservices/icmdexec.h" +#include "coreservices/isrccode.h" +#include "coreservices/iclock.h" +#include "coreservices/iwire.h" +#include "coreservices/irawlistener.h" + +namespace debugger { + +class TcpCommands : public IRawListener, + public IHap, + public IClockListener { + public: + explicit TcpCommands(IService *parent); + ~TcpCommands(); + + /** IRawListener interface */ + virtual void updateData(const char *buf, int buflen); + + /** IHap */ + virtual void hapTriggered(IFace *isrc, EHapType type, const char *descr); + + /** IClockListener */ + virtual void stepCallback(uint64_t t); + + /** Common acccess methods */ + AttributeType *response(); + + protected: + IFace *getInterface(const char *name) { + return parent_->getInterface(name); + } + + private: + void processCommand(); + void br_add(const AttributeType &symb, AttributeType *res); + void br_rm(const AttributeType &symb, AttributeType *res); + void go_msec(const AttributeType &symb, AttributeType *res); + void go_until(const AttributeType &symb, AttributeType *res); + void step(int cnt, AttributeType *res); + void symb2addr(const char *symbol, AttributeType *res); + void power_on(AttributeType *res); + void power_off(AttributeType *res); + + private: + char rxbuf_[4096]; + int rxcnt_; + AttributeType cpu_; + AttributeType executor_; + AttributeType source_; + + AttributeType resp_; + + IService *parent_; + ICmdExecutor *iexec_; + ISourceCode *isrc_; + ICpuRiscV *iriscv_; + IClock *iclk_; + AttributeType *cpuLogLevel_; + + event_def eventHalt_; + event_def eventDelayMs_; + event_def eventPowerChanged_; +}; + +} // namespace debugger + +#endif // __DEBUGGER_TCPCMD_H__
src/libdbg64g/services/remote/tcpcmd.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/libdbg64g/services/remote/tcpserver.cpp =================================================================== --- src/libdbg64g/services/remote/tcpserver.cpp (nonexistent) +++ src/libdbg64g/services/remote/tcpserver.cpp (revision 5) @@ -0,0 +1,229 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Remote access to debugger via TCP connection. Server side. + */ + +#include "tcpserver.h" + +namespace debugger { + +/** Class registration in the Core */ +REGISTER_CLASS(TcpServer) + +TcpServer::TcpServer(const char *name) : IService(name) { + registerInterface(static_cast(this)); + registerAttribute("Enable", &isEnable_); + registerAttribute("Timeout", &timeout_); + registerAttribute("BlockingMode", &blockmode_); + registerAttribute("HostIP", &hostIP_); + registerAttribute("HostPort", &hostPort_); +} + +void TcpServer::postinitService() { + createServerSocket(); + + if (listen(hsock_, 1) < 0) { + RISCV_error("listen() failed", 0); + return; + } + + /** By default socket was created with Blocking mode */ + if (!blockmode_.to_bool()) { + setBlockingMode(false); + } + + if (isEnable_.to_bool()) { + if (!run()) { + RISCV_error("Can't create thread.", NULL); + return; + } + } +} + +void TcpServer::busyLoop() { + socket_def client_sock; + int err; + + fd_set readSet; + timeval timeout; + timeout.tv_sec = 0; + timeout.tv_usec = 400000; // 400 ms + + int idx = 0; + char tname[64]; + + IClass *icls; + IService *isrv; + while (isEnabled()) { + FD_ZERO(&readSet); + FD_SET(hsock_, &readSet); + err = select(hsock_ + 1, &readSet, NULL, NULL, &timeout); + if (err > 0) { + client_sock = accept(hsock_, 0, 0); + setRcvTimeout(client_sock, timeout_.to_int()); + RISCV_sprintf(tname, sizeof(tname), "client%d", idx++); + + icls = static_cast(RISCV_get_class("TcpClientClass")); + isrv = icls->createService(tname); + AttributeType lst, item; + lst.make_list(0); + item.make_list(2); + item[0u].make_string("LogLevel"); + item[1].make_int64(4); + lst.add_to_list(&item); + item[0u].make_string("Enable"); + item[1].make_boolean(true); + lst.add_to_list(&item); + + isrv->initService(&lst); + IThread *ithrd = + static_cast(isrv->getInterface(IFACE_THREAD)); + ithrd->setExtArgument(&client_sock); + isrv->postinitService(); + RISCV_info("TCP %s %p started", isrv->getObjName(), client_sock); + } else if (err == 0) { + // timeout + } else { + RISCV_info("TCP server thread accept() failed", 0); + loopEnable_.state = false; + } + } + closeServerSocket(); +} + +int TcpServer::createServerSocket() { + char hostName[256]; + if (gethostname(hostName, sizeof(hostName)) < 0) { + return -1; + } + + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + /** + * Check availability of IPv4 address assigned via attribute 'hostIP'. + * If it woudn't be found use the last avaialble IP address. + */ + int retval; + struct addrinfo *result = NULL; + struct addrinfo *ptr = NULL; + retval = getaddrinfo(hostName, "0", &hints, &result); + if (retval != 0) { + return -1; + } + + if (hostIP_.size() == 0 || hostIP_.is_equal("127.0.0.1")) { + memset(&sockaddr_ipv4_, 0, sizeof(struct sockaddr_in)); + sockaddr_ipv4_.sin_family = AF_INET; + sockaddr_ipv4_.sin_addr.s_addr = inet_addr("127.0.0.1"); + } else { + for (ptr = result; ptr != NULL; ptr = ptr->ai_next) { + // Find only IPV4 address, ignore others. + if (ptr->ai_family != AF_INET) { + continue; + } + sockaddr_ipv4_ = *((struct sockaddr_in *)ptr->ai_addr); + + if (hostIP_.is_equal(inet_ntoa(sockaddr_ipv4_.sin_addr))) { + break; + } + } + } + sockaddr_ipv4_.sin_port = htons(static_cast(hostPort_.to_int())); + RISCV_info("Selected Host IPv4 %s:%d", + inet_ntoa(sockaddr_ipv4_.sin_addr), + hostPort_.to_uint32()); + + hsock_ = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (hsock_ < 0) { + RISCV_error("%s", "Error: socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)"); + return -1; + } + + int res = bind(hsock_, + reinterpret_cast(&sockaddr_ipv4_), + sizeof(sockaddr_ipv4_)); + if (res != 0) { + RISCV_error("Error: bind(hsock_, \"%s\", ...)", hostIP_.to_string()); + return -1; + } + + addr_size_t addr_sz = sizeof(sockaddr_ipv4_); + res = getsockname(hsock_, + reinterpret_cast(&sockaddr_ipv4_), + &addr_sz); + + RISCV_info("IPv4 address %s:%d . . . opened", + inet_ntoa(sockaddr_ipv4_.sin_addr), + ntohs(sockaddr_ipv4_.sin_port)); + + return 0; +} + +void TcpServer::setRcvTimeout(socket_def skt, int timeout_ms) { + if (!timeout_ms) { + return; + } + struct timeval tv; +#if defined(_WIN32) || defined(__CYGWIN__) + /** On windows timeout of the setsockopt() function is the DWORD + * size variable in msec, so we use only the first field in timeval + * struct and directly assgign argument. + */ + tv.tv_sec = timeout_ms; + tv.tv_usec = 0; +#else + tv.tv_usec = (timeout_ms % 1000) * 1000; + tv.tv_sec = timeout_ms / 1000; +#endif + setsockopt(skt, SOL_SOCKET, SO_RCVTIMEO, + reinterpret_cast(&tv), sizeof(struct timeval)); +} + +bool TcpServer::setBlockingMode(bool mode) { + int ret; +#if defined(_WIN32) || defined(__CYGWIN__) + // 0 = disable non-blocking mode + // 1 = enable non-blocking mode + u_long arg = mode ? 0 : 1; + ret = ioctlsocket(hsock_, FIONBIO, &arg); + if (ret == SOCKET_ERROR) { + RISCV_error("Set non-blocking socket failed", 0); + } +#else + int flags = fcntl(hsock_, F_GETFL, 0); + if (flags < 0) { + return false; + } + flags = mode ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); + ret = fcntl(hsock_, F_SETFL, flags); +#endif + if (ret == 0) { + // success + blockmode_.make_boolean(mode); + return true; + } + return false; +} + +void TcpServer::closeServerSocket() { + if (hsock_ < 0) { + return; + } + +#if defined(_WIN32) || defined(__CYGWIN__) + closesocket(hsock_); +#else + shutdown(hsock_, SHUT_RDWR); + close(hsock_); +#endif + hsock_ = -1; +} + + +} // namespace debugger
src/libdbg64g/services/remote/tcpserver.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/libdbg64g/services/remote/tcpserver.h =================================================================== --- src/libdbg64g/services/remote/tcpserver.h (nonexistent) +++ src/libdbg64g/services/remote/tcpserver.h (revision 5) @@ -0,0 +1,52 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Remote access to debugger via TCP connection. Server side. + */ + +#ifndef __DEBUGGER_TCPSERVER_H__ +#define __DEBUGGER_TCPSERVER_H__ + +#include +#include +#include "coreservices/ithread.h" +#include "tcpclient.h" + +namespace debugger { + +class TcpServer : public IService, + public IThread { + public: + explicit TcpServer(const char *name); + + /** IService interface */ + virtual void postinitService(); + + protected: + /** IThread interface */ + virtual void busyLoop(); + + protected: + int createServerSocket(); + void closeServerSocket(); + void setRcvTimeout(socket_def skt, int timeout_ms); + bool setBlockingMode(bool mode); + + private: + AttributeType isEnable_; + AttributeType timeout_; + AttributeType blockmode_; + AttributeType hostIP_; + AttributeType hostPort_; + + struct sockaddr_in sockaddr_ipv4_; + socket_def hsock_; + char rcvbuf[4096]; +}; + +DECLARE_CLASS(TcpServer) + +} // namespace debugger + +#endif // __DEBUGGER_TCPSERVER_H__
src/libdbg64g/services/remote/tcpserver.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/socsim_plugin/hardreset.cpp =================================================================== --- src/socsim_plugin/hardreset.cpp (nonexistent) +++ src/socsim_plugin/hardreset.cpp (revision 5) @@ -0,0 +1,53 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Hardreset module. + */ + +#include +#include "hardreset.h" + +namespace debugger { + +HardReset::HardReset(const char *name) : IService(name) { + registerInterface(static_cast(this)); + registerAttribute("ResetDevices", + static_cast(&resetDevices_)); +} + +void HardReset::postinitService() { + const char *devname, *portname; + IFace *irst; + AttributeType item; + for (unsigned i = 0; i < resetDevices_.size(); i++) { + AttributeType &dev = resetDevices_[i]; + if (dev.is_string()) { + devname = dev.to_string(); + irst = RISCV_get_service_iface(devname, IFACE_RESET_LISTENER); + } else if (dev.is_list() && dev.size() >= 2) { + devname = dev[0u].to_string(); + portname = dev[1].to_string(); + irst = RISCV_get_service_port_iface(devname, portname, + IFACE_RESET_LISTENER); + } + + if (irst) { + item.make_iface(irst); + resetListeners_.add_to_list(&item); + } else { + RISCV_error("%s hasn't IResetListener itnerface", devname); + } + } +} + +void HardReset::powerOnPressed() { + reset(true); +} + +void HardReset::powerOnReleased() { + reset(false); +} + +} // namespace debugger +
src/socsim_plugin/hardreset.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/socsim_plugin/hardreset.h =================================================================== --- src/socsim_plugin/hardreset.h (nonexistent) +++ src/socsim_plugin/hardreset.h (revision 5) @@ -0,0 +1,37 @@ +/** + * @file + * @copyright Copyright 2017 GNSS Sensor Ltd. All right reserved. + * @author Sergey Khabarov - sergeykhbr@gmail.com + * @brief Hardreset module. + */ + +#ifndef __SOCSIM_PLUGIN_HARDRESET_H__ +#define __SOCSIM_PLUGIN_HARDRESET_H__ + +#include +#include +#include "coreservices/ireset.h" + +namespace debugger { + +class HardReset : public IService, + public IReset { + public: + HardReset(const char *name); + + /** IService interface */ + virtual void postinitService(); + + /** IReset interface (generic) */ + virtual void powerOnPressed(); + virtual void powerOnReleased(); + + private: + AttributeType resetDevices_; +}; + +DECLARE_CLASS(HardReset) + +} // namespace debugger + +#endif // __SOCSIM_PLUGIN_HARDRESET_H__
src/socsim_plugin/hardreset.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: src/socsim_plugin/uartmst.cpp =================================================================== --- src/socsim_plugin/uartmst.cpp (nonexistent) +++ src/socsim_plugin/uartmst.cpp (revision 5) @@ -0,0 +1,188 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Packet format: + * Write command: + * Send [11.Length-1].Addr[63:0].Data[31:0]*(x Length) + * Read command: + * Send [10.Length-1].Addr[63:0] + * Receive Data[31:0]*(x Length) + */ + +#include "api_core.h" +#include "uartmst.h" +#include "coreservices/isocinfo.h" + +namespace debugger { + +static const uint32_t UART_STATUS_TX_FULL = 0x00000001; +static const uint32_t UART_STATUS_TX_EMPTY = 0x00000002; +static const uint32_t UART_STATUS_RX_FULL = 0x00000010; +static const uint32_t UART_STATUS_RX_EMPTY = 0x00000020; +static const uint32_t UART_STATUS_ERR_PARITY = 0x00000100; +static const uint32_t UART_STATUS_ERR_STOPBIT = 0x00000200; +static const uint32_t UART_CONTROL_RX_IRQ_ENA = 0x00002000; +static const uint32_t UART_CONTROL_TX_IRQ_ENA = 0x00004000; +static const uint32_t UART_CONTROL_PARITY_ENA = 0x00008000; + + +UartMst::UartMst(const char *name) : IService(name) { + registerInterface(static_cast(this)); + registerInterface(static_cast(this)); + registerInterface(static_cast(this)); + registerAttribute("Bus", &bus_); + + listeners_.make_list(0); + bus_.make_string(""); + + RISCV_event_create(&event_tap_, "UartMst_event_tap"); + RISCV_event_create(&event_request_, "UartMst_event_request"); + RISCV_event_create(&event_accept_, "UartMst_event_accept"); + RISCV_mutex_init(&mutexListeners_); + + memset(®s_, 0, sizeof(regs_)); + regs_.status = UART_STATUS_TX_EMPTY | UART_STATUS_RX_EMPTY; + + txbuf_sz_ = 0; + baudrate_detect_ = false; +} + +UartMst::~UartMst() { + RISCV_event_close(&event_tap_); + RISCV_event_close(&event_request_); + RISCV_event_close(&event_accept_); + RISCV_mutex_destroy(&mutexListeners_); +} + +void UartMst::postinitService() { + ibus_ = static_cast( + RISCV_get_service_iface(bus_.to_string(), IFACE_MEMORY_OPERATION)); + if (!ibus_) { + RISCV_error("Can't find IBus interface %s", bus_.to_string()); + } + run(); +} + +void UartMst::busyLoop() { + UartMstPacketType packet; + RISCV_info("UartMst thread was started", NULL); + trans_.source_idx = CFG_NASTI_MASTER_MSTUART; // Hardcoded in VHDL value + + int burst_sz; + while (isEnabled()) { + if (RISCV_event_wait_ms(&event_request_, 50) != 0) { + continue; + } + RISCV_event_clear(&event_request_); + memcpy(&packet, txbuf_.buf, sizeof(packet)); + RISCV_event_set(&event_accept_); + txbuf_sz_ = 0; + + if (!baudrate_detect_) { + // Symbol 0x55 runs baudrate detector + if (packet.cmd == 0x55) { + baudrate_detect_ = true; + } + continue; + } + + if ((packet.cmd & 0x80) == 0) { + RISCV_error("Wrong request format", NULL); + continue; + } + + trans_.addr = packet.addr.val & 0xFFFFFFFF; + trans_.xsize = 4; + if ((packet.cmd & 0x40) == 0) { + trans_.action = MemAction_Read; + } else { + trans_.action = MemAction_Write; + trans_.wstrb = (1 << trans_.xsize) - 1; + } + + burst_sz = (packet.cmd & 0x3F) + 1; + for (int i = 0; i < burst_sz; i++) { + if (trans_.action == MemAction_Write) { + trans_.wpayload.b32[0] = packet.data[0].buf32[i]; + } + RISCV_event_clear(&event_tap_); + ibus_->nb_transport(&trans_, this); + if (RISCV_event_wait_ms(&event_tap_, 500) != 0) { + RISCV_error("CPU queue callback timeout", NULL); + } else if (trans_.action == MemAction_Read) { + RISCV_mutex_lock(&mutexListeners_); + for (unsigned n = 0; n < listeners_.size(); n++) { + IRawListener *lstn = static_cast( + listeners_[n].to_iface()); + lstn->updateData( + reinterpret_cast(trans_.rpayload.b8), + trans_.xsize); + } + RISCV_mutex_unlock(&mutexListeners_); + } + trans_.addr += 4; + } + } +} + +int UartMst::writeData(const char *buf, int sz) { + if (sz > static_cast(sizeof(UartMstPacketType))) { + RISCV_error("Request will be truncated", NULL); + sz = sizeof(UartMstPacketType); + } + memcpy(txbuf_.buf, buf, sz); + txbuf_sz_ = sz; + RISCV_event_clear(&event_accept_); + RISCV_event_set(&event_request_); + RISCV_event_wait_ms(&event_accept_, 500); + return sz; +} + +void UartMst::registerRawListener(IFace *listener) { + AttributeType lstn(listener); + RISCV_mutex_lock(&mutexListeners_); + listeners_.add_to_list(&lstn); + RISCV_mutex_unlock(&mutexListeners_); +} + +void UartMst::unregisterRawListener(IFace *listener) { + RISCV_mutex_lock(&mutexListeners_); + for (unsigned i = 0; i < listeners_.size(); i++) { + IFace *iface = listeners_[i].to_iface(); + if (iface == listener) { + listeners_.remove_from_list(i); + break; + } + } + RISCV_mutex_unlock(&mutexListeners_); +} + +void UartMst::getListOfPorts(AttributeType *list) { + list->make_list(0); +} + +int UartMst::openPort(const char *port, AttributeType settings) { + return 0; +} + +void UartMst::closePort() { +} + +void UartMst::nb_response(Axi4TransactionType *trans) { + RISCV_event_set(&event_tap_); +} + +} // namespace debugger +
src/socsim_plugin/uartmst.cpp Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: src/socsim_plugin/uartmst.h =================================================================== --- src/socsim_plugin/uartmst.h (nonexistent) +++ src/socsim_plugin/uartmst.h (revision 5) @@ -0,0 +1,101 @@ +/* + * Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __DEBUGGER_SOCSIM_PLUGIN_UARTMST_H__ +#define __DEBUGGER_SOCSIM_PLUGIN_UARTMST_H__ + +#include "iclass.h" +#include "iservice.h" +#include "coreservices/ithread.h" +#include "coreservices/imemop.h" +#include "coreservices/iserial.h" +#include "coreservices/iwire.h" +#include "coreservices/irawlistener.h" +#include "coreservices/imemop.h" +#include + +namespace debugger { + +static const int UART_MST_BURST_MAX = 64; + +#pragma pack(1) +struct UartMstPacketType { + uint8_t cmd; + Reg64Type addr; + Reg64Type data[UART_MST_BURST_MAX]; +}; +#pragma pack() + +class UartMst : public IService, + public IThread, + public IAxi4NbResponse, + public ISerial { +public: + UartMst(const char *name); + ~UartMst(); + + /** IService interface */ + virtual void postinitService(); + + /** ISerial */ + virtual int writeData(const char *buf, int sz); + virtual void registerRawListener(IFace *listener); + virtual void unregisterRawListener(IFace *listener); + virtual void getListOfPorts(AttributeType *list); + virtual int openPort(const char *port, AttributeType settings); + virtual void closePort(); + + /** IAxi4NbResponse */ + virtual void nb_response(Axi4TransactionType *trans); + +protected: + /** IThread interface */ + virtual void busyLoop(); + +private: + AttributeType listeners_; // non-registering attribute + AttributeType bus_; + + IMemoryOperation *ibus_; + ISerial *itransport_; + + Axi4TransactionType trans_; + + mutex_def mutexListeners_; + event_def event_request_; + event_def event_accept_; + event_def event_tap_; + + union TxBufferType { + UartMstPacketType packet; + uint8_t buf[sizeof(UartMstPacketType)]; + } txbuf_; + int txbuf_sz_; + bool baudrate_detect_; + + struct uart_map { + volatile uint32_t status; + volatile uint32_t scaler; + uint32_t rsrv[2]; + volatile uint32_t data; + } regs_; +}; + +DECLARE_CLASS(UartMst) + +} // namespace debugger + +#endif // __DEBUGGER_SOCSIM_PLUGIN_UARTMST_H__
src/socsim_plugin/uartmst.h Property changes : Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +Author Date Id Rev URL \ No newline at end of property Index: targets/fpga_gui_uartdbg.json =================================================================== --- targets/fpga_gui_uartdbg.json (nonexistent) +++ targets/fpga_gui_uartdbg.json (revision 5) @@ -0,0 +1,122 @@ +{ + 'GlobalSettings':{ + 'SimEnable':false, + 'GUI':true, + 'ScriptFile':'', + 'Description':'This configuration instantiates functional RISC-V model' + }, + 'Services':[ + {'Class':'GuiPluginClass','Instances':[ + {'Name':'gui0','Attr':[ + ['LogLevel',4], + ['WidgetsConfig',{ + 'Serial':'port1', + 'AutoComplete':'autocmd0', + 'SocInfo':'info0', + 'PollingMs':250, + 'EventsLoopMs':10, + 'RegsViewWidget':{ + 'RegList':[['ra', 's0', 'a0'], + ['sp', 's1', 'a1'], + ['gp', 's2', 'a2'], + ['tp', 's3', 'a3'], + ['' , 's4', 'a4'], + ['t0', 's5', 'a5'], + ['t1', 's6', 'a6'], + ['t2', 's7', 'a7'], + ['t3', 's8', ''], + ['t4', 's9', ''], + ['t5', 's10', 'pc'], + ['t6', 's11', 'npc']], + 'RegWidthBytes':8, + } + }], + ['SocInfo','info0'], + ['CommandExecutor','cmdexec0'] + ]}]}, + {'Class':'SerialDbgServiceClass','Instances':[ + {'Name':'uarttap','Attr':[ + ['LogLevel',1], + ['Timeout',1000], + ['Port','port1']]}]}, + {'Class':'ComPortServiceClass','Instances':[ + {'Name':'port1','Attr':[ + ['LogLevel',2], + ['Enable',true], + ['UartSim',''], + ['LogFile','uart0.log'], + ['ComPortName','COM3'], + ['ComPortSpeed',115200]]}]}, + {'Class':'ElfReaderServiceClass','Instances':[ + {'Name':'loader0','Attr':[ + ['LogLevel',4], + ['SourceProc','src0']]}]}, + {'Class':'ConsoleServiceClass','Instances':[ + {'Name':'console0','Attr':[ + ['LogLevel',4], + ['Enable',true], + ['StepQueue','core0'], + ['AutoComplete','autocmd0'], + ['CommandExecutor','cmdexec0'], + ['DefaultLogFile','default.log'], + ['Signals','gpio0'], + ['InputPort','port1']]}]}, + {'Class':'AutoCompleterClass','Instances':[ + {'Name':'autocmd0','Attr':[ + ['LogLevel',4], + ['SocInfo','info0'] + ['HistorySize',64], + ['History',[ + 'csr MCPUID', + 'csr MTIME', + 'read 0xfffff004 128', + 'loadelf helloworld' + ]] + ]}]}, + {'Class':'CmdExecutorClass','Instances':[ + {'Name':'cmdexec0','Attr':[ + ['LogLevel',4], + ['Tap','uarttap'], + ['SocInfo','info0'] + ]}]}, + {'Class':'SocInfoClass','Instances':[ + {'Name':'info0','Attr':[ + ['LogLevel',4], + ['PnpBaseAddress',0xFFFFF000], + ['GpioBaseAddress',0x80000000], + ['DsuBaseAddress',0x80080000], + ['ListRegs',[['zero',8,0x08000],['ra',8,0x08008],['sp',8,0x08010],['gp',8,0x08018], + ['tp',8,0x08020],['t0',8,0x08028],['t1',8,0x08030],['t2',8,0x08038], + ['s0',8,0x08040],['s1',8,0x08048],['a0',8,0x08050],['a1',8,0x08058], + ['a2',8,0x08060],['a3',8,0x08068],['a4',8,0x08070],['a5',8,0x08078], + ['a6',8,0x08080],['a7',8,0x08088],['s2',8,0x08090],['s3',8,0x08098], + ['s4',8,0x080A0],['s5',8,0x080A8],['s6',8,0x080B0],['s7',8,0x080B8], + ['s8',8,0x080C0],['s9',8,0x080C8],['s10',8,0x080D0],['s11',8,0x080D8], + ['t3',8,0x080E0],['t4',8,0x080E8],['t5',8,0x080F0],['t6',8,0x080F8], + ['pc',8,0x08100,'Instruction Pointer'], + ['npc',8,0x08108,'Next IP']]], + ['ListCSR',[ + ['MISA',8,0xf10,'Architecture and supported set of instructions'], + ['MVENDORID',8,0xf11,'Vecndor ID'], + ['MARCHID',8,0xf12,'Architecture ID'], + ['MIMPLEMENTATIONID',8,0xf13,'Implementation ID'], + ['MHARTID',8,0xf14,'Thread ID'], + ['MTIME',8,0x701,'Machine wall-clock time.'], + ['MSTATUS',8,0x300,'Machine mode status register.'], + ['MIE',8,0x304,'Machine interrupt enable register.'], + ['MTVEC',8,0x305,'Machine mode trap vector register.'], + ['MSCRATCH',8,0x340,'Machine mode scratch register.'], + ['MEPC',8,0x341,'Machine exception program counter'], + ['MCAUSE',8,0x342,'Machine cause trap register'], + ['MBADADDR',8,0x343,'Machine mode bad address register'], + ['MIP',8,0x344,'Machine mode interrupt pending bits register'] + ]]]}]}, + {'Class':'RiscvSourceServiceClass','Instances':[ + {'Name':'src0','Attr':[ + ['LogLevel',4]]}]}, + {'Class':'SimplePluginClass','Instances':[ + {'Name':'example0','Attr':[ + ['LogLevel',4], + ['attr1','This is test attr value']]}]}, + ] +} Index: targets/functional_arm_gui.json =================================================================== --- targets/functional_arm_gui.json (nonexistent) +++ targets/functional_arm_gui.json (revision 5) @@ -0,0 +1,300 @@ +{ + 'GlobalSettings':{ + 'SimEnable':true, + 'GUI':true, + 'ScriptFile':'', + 'Description':'This configuration instantiates functional RISC-V model' + }, + 'Services':[ + {'Class':'GuiPluginClass','Instances':[ + {'Name':'gui0','Attr':[ + ['LogLevel',4], + ['WidgetsConfig',{ + 'Serial':'port1', + 'AutoComplete':'autocmd0', + 'SocInfo':'info0', + 'PollingMs':250, + 'EventsLoopMs':10, + 'RegsViewWidget':{ + 'RegList':[['r0'],['r1'],['r2'],['r3'],[""], ['r4'],['r5'],['r6'],['r7'], + ['r8'],['r9'],['r10'],['r11'],[""], ['fp'],['sp'],['lr'],['pc'], + [''],['npc'],[''],['cpsr']], + 'RegWidthBytes':4, + } + }], + ['SocInfo','info0'], + ['CommandExecutor','cmdexec0'] + ]}]}, + {'Class':'SerialDbgServiceClass','Instances':[ + {'Name':'uarttap','Attr':[ + ['LogLevel',1], + ['Port','uartmst0'], + ['Timeout',500]]}]}, + {'Class':'EdclServiceClass','Instances':[ + {'Name':'edcltap','Attr':[ + ['LogLevel',1], + ['Transport','udpedcl'], + ['seq_cnt',0]]}]}, + {'Class':'UdpServiceClass','Instances':[ + {'Name':'udpboard','Attr':[ + ['LogLevel',1], + ['Timeout',0x190]]}, + {'Name':'udpedcl','Attr':[ + ['LogLevel',1], + ['Timeout',0x3e8], + ['HostIP','192.168.0.53'], + ['BoardIP','192.168.0.51']]}]}, + {'Class':'TcpServerClass','Instances':[ + {'Name':'rpcserver','Attr':[ + ['LogLevel',4], + ['Enable',true], + ['Timeout',500], + ['BlockingMode',true], + ['HostIP',''], + ['HostPort',8687]]}]}, + {'Class':'ComPortServiceClass','Instances':[ + {'Name':'port1','Attr':[ + ['LogLevel',2], + ['Enable',true], + ['UartSim','uart0'], + ['ComPortName','COM3'], + ['ComPortSpeed',115200]]}]}, + {'Class':'ElfReaderServiceClass','Instances':[ + {'Name':'loader0','Attr':[ + ['LogLevel',4], + ['SourceProc','src0']]}]}, + {'Class':'ConsoleServiceClass','Instances':[ + {'Name':'console0','Attr':[ + ['LogLevel',4], + ['Enable',true], + ['StepQueue','core0'], + ['AutoComplete','autocmd0'], + ['CommandExecutor','cmdexec0'], + ['DefaultLogFile','default.log'], + ['Signals','gpio0'], + ['InputPort','port1']]}]}, + {'Class':'AutoCompleterClass','Instances':[ + {'Name':'autocmd0','Attr':[ + ['LogLevel',4], + ['SocInfo','info0'] + ['HistorySize',64], + ['History',[ + 'csr MCPUID', + 'csr MTIME', + 'read 0xfffff004 128', + 'loadelf helloworld', + 'loadelf e:/zephyr.elf nocode', + ]] + ]}]}, + {'Class':'CmdExecutorClass','Instances':[ + {'Name':'cmdexec0','Attr':[ + ['LogLevel',4], + ['Tap','edcltap'], + ['SocInfo','info0'] + ]}]}, + {'Class':'SocInfoClass','Instances':[ + {'Name':'info0','Attr':[ + ['LogLevel',4], + ['DsuBaseAddress',0x80080000], + ['ListRegs',[['r0',4,0x08000], + ['r1',4,0x08008], + ['r2',4,0x08010], + ['r3',4,0x08018], + ['r4',4,0x08020], + ['r5',4,0x08028], + ['r6',4,0x08030], + ['r7',4,0x08038], + ['r8',4,0x08040], + ['r9',4,0x08048], + ['r10',4,0x08050], + ['r11',4,0x08058], + ['fp',4,0x08060], + ['sp',4,0x08068], + ['lr',4,0x08070], + ['cpsr',4,0x08080], + ['pc',4,0x08100], + ['npc',4,0x08108] + ]] + ]}]}, + {'Class':'SimplePluginClass','Instances':[ + {'Name':'example0','Attr':[ + ['LogLevel',4], + ['attr1','This is test attr value']]}]}, + {'Class':'ArmSourceServiceClass','Instances':[ + {'Name':'src0','Attr':[ + ['LogLevel',4], + ['Endianess',0, '0=LSB (x86); 1=MSB(ARM)'], + ]}]}, + {'Class':'GrethClass','Instances':[ + {'Name':'greth0','Attr':[ + ['LogLevel',1], + ['BaseAddress',0x80040000], + ['Length',0x40000], + ['SysBusMasterID',2,'Hardcoded in VHDL'], + ['IP',0x55667788], + ['MAC',0xfeedface00], + ['Bus','axi0'], + ['Transport','udpboard'] + ]}]}, + {'Class':'CpuCortex_FunctionalClass','Instances':[ + {'Name':'core0','Attr':[ + ['Enable',true], + ['LogLevel',3], + ['SysBusMasterID',0,'Used to gather Bus statistic'], + ['SysBus','axi0'], + ['DbgBus','dbgbus0'], + ['SysBusWidthBytes',4,'Split dma transactions from CPU'], + ['StackTraceSize',64,'Number of 16-bytes entries'], + ['ResetVector',0x0000], + ['FreqHz',60000000], + ['SysBusMasterID',0], + ['SourceCode','src0'], + ['GenerateRegTraceFile',false,'Generate Registers modification file to compare with SystemC'], + ['GenerateMemTraceFile',false,'Generate Memory access file to compare with SystemC'], + ]}]}, + {'Class':'MemorySimClass','Instances':[ + {'Name':'bootrom0','Attr':[ + ['LogLevel',1], + ['InitFile','../../../examples/bootarm/linuxbuild/bin/bootimage.hex'], + ['ReadOnly',true], + ['BaseAddress',0x0], + ['Length',8192] + ]}]}, + {'Class':'MemorySimClass','Instances':[ + {'Name':'fwimage0','Attr':[ + ['LogLevel',1], + ['InitFile','../../../examples/dhrystone21/makefiles/bin/dhrystone21.hex'], + ['ReadOnly',true], + ['BaseAddress',0x00100000], + ['Length',0x40000] + ]}]}, + {'Class':'MemorySimClass','Instances':[ + {'Name':'sram0','Attr':[ + ['LogLevel',1], + ['InitFile','../../../examples/dhrystone21/makefiles/bin/dhrystone21.hex'], + ['ReadOnly',false], + ['BaseAddress',0x10000000], + ['Length',0x80000] + ]}]}, + {'Class':'GPIOClass','Instances':[ + {'Name':'gpio0','Attr':[ + ['LogLevel',3], + ['BaseAddress',0x80000000], + ['Length',4096], + ['DIP',0x1] + ]}]}, + {'Class':'UARTClass','Instances':[ + {'Name':'uart0','Attr':[ + ['LogLevel',1], + ['BaseAddress',0x80001000], + ['Length',4096], + ['IrqControl',['irqctrl0','irq1']], + ['AutoTestEna',false,'Enable/Disable automatic test input via serial interface'], + ['TestCases',[[22097,'s'], + [22500,'et'], + [24399,'_mo'], + [25780,'dul'], + [28999,'e s'], + [31599,'oc'], + [32599,'\r\n'], + [48599,'dhr'], + [49599,'y\r\n']]] + + ]}]}, + {'Class':'IrqControllerClass','Instances':[ + {'Name':'irqctrl0','Attr':[ + ['LogLevel',1], + ['BaseAddress',0x80002000], + ['Length',4096], + ['CPU','core0'], + ['IrqTotal',4], + ['CSR_MIPI',0x783] + ]}]}, + {'Class':'DSUClass','Instances':[ + {'Name':'dsu0','Attr':[ + ['LogLevel',1], + ['BaseAddress',0x80080000], + ['Length',0x20000], + ['CPU','core0'], + ['Bus','axi0'] + ]}]}, + {'Class':'GNSSStubClass','Instances':[ + {'Name':'gnss0','Attr':[ + ['LogLevel',1], + ['BaseAddress',0x80003000], + ['Length',4096], + ['IrqControl',['irqctrl0','irq5']], + ['ClkSource','core0'] + ]}]}, + {'Class':'RfControllerClass','Instances':[ + {'Name':'rfctrl0','Attr':[ + ['LogLevel',1], + ['BaseAddress',0x80004000], + ['Length',4096] + ]}]}, + {'Class':'GPTimersClass','Instances':[ + {'Name':'gptmr0','Attr':[ + ['LogLevel',1], + ['BaseAddress',0x80005000], + ['Length',4096], + ['IrqControl',['irqctrl0','irq3']], + ['ClkSource','core0'] + ]}]}, + {'Class':'UartMstClass','Instances':[ + {'Name':'uartmst0','Attr':[ + ['LogLevel',1], + ['Bus','axi0'] + ]}]}, + {'Class':'FseV2Class','Instances':[ + {'Name':'fsegps0','Attr':[ + ['LogLevel',1], + ['BaseAddress',0x80008000], + ['Length',4096] + ]}]}, + {'Class':'PNPClass','Instances':[ + {'Name':'pnp0','Attr':[ + ['LogLevel',4], + ['BaseAddress',0xfffff000], + ['Length',4096], + ['Tech',0], + ['AdcDetector',0xff] + ]}]}, + {'Class':'BusClass','Instances':[ + {'Name':'axi0','Attr':[ + ['LogLevel',3], + ['DSU','dsu0'], + ['MapList',['bootrom0','fwimage0','sram0','gpio0', + 'uart0','irqctrl0','gnss0','gptmr0', + 'pnp0','dsu0','greth0','rfctrl0','fsegps0']] + ]}]}, + {'Class':'BusClass','Instances':[ + {'Name':'dbgbus0','Attr':[ + ['LogLevel',3], + ['MapList',[['core0','pc'], + ['core0','npc'], + ['core0','status'], + ['core0','regs'], + ['core0','stepping_cnt'], + ['core0','clock_cnt'], + ['core0','executed_cnt'], + ['core0','stack_trace_cnt'], + ['core0','stack_trace_buf'], + ['core0','br_fetch_addr'], + ['core0','br_fetch_instr'], + ['core0','br_hw_add'], + ['core0','br_hw_remove'], + ]] + ]}]}, + {'Class':'HardResetClass','Instances':[ + {'Name':'reset0','Attr':[ + ['LogLevel',4], + ['ResetDevices',[ + 'core0' + ]] + ]}]}, + {'Class':'BoardSimClass','Instances':[ + {'Name':'boardsim','Attr':[ + ['LogLevel',1] + ]}]} + ] +}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.