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 eective address by adding the
+ * zero-extended oset, 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 eective address by adding the
+ * zero-extended oset, 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 eective address by adding the zero-extended oset, 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 eective address by adding the
+ * zero-extended oset, 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 eective address by adding the
+ * zero-extended oset, 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 oset, 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 oset, 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]
+ ]}]}
+ ]
+}