Skip to content

Commit

Permalink
coreserver: Add support for instruction time measurements
Browse files Browse the repository at this point in the history
Signed-off-by: Michael Buesch <m@bues.ch>
  • Loading branch information
mbuesch committed Feb 4, 2019
1 parent 05c4273 commit ccef7e1
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 12 deletions.
18 changes: 17 additions & 1 deletion awlsim-client
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ def usage():
print("Actions to be performed on the server:")
print(" -r|--runstate RUN/STOP Set the run state of the CPU.")
print(" -S|--stats Fetch and display CPU statistics.")
print(" --meas-start Start instruction time measurements.")
print(" --meas-stop Stop instruction time measurements.")
print(" --shutdown Shutdown the core server system.")
print(" --reboot Reboot the core server system.")

Expand All @@ -116,7 +118,7 @@ def main():
"hc:t:L:sP:r:S",
[ "help", "connect=", "timeout=", "loglevel=",
"ssh-tunnel", "ssh-passphrase=", "ssh-user=", "ssh-port=", "ssh-localport=", "ssh-exe=",
"runstate=", "stats", "shutdown", "reboot", ])
"runstate=", "stats", "meas-start", "meas-stop", "shutdown", "reboot", ])
except getopt.GetoptError as e:
printError(str(e))
usage()
Expand Down Expand Up @@ -179,6 +181,10 @@ def main():
sys.exit(1)
if o in ("-S", "--stats"):
actions.append(("stats", None))
if o == "--meas-start":
actions.append(("meas-start", None))
if o == "--meas-stop":
actions.append(("meas-stop", None))
if o == "--shutdown":
actions.append(("shutdown", None))
if o == "--reboot":
Expand Down Expand Up @@ -219,6 +225,16 @@ def main():
client.setRunState(actionValue)
elif action == "stats":
printCpuStats(client.getCpuStats(sync=True))
elif action == "meas-start":
if not client.measStart():
printError("Failed to start measurements.")
elif action == "meas-stop":
reportData = client.measStop()
if reportData:
sys.stdout.write(reportData)
sys.stdout.flush()
else:
printError("Measurement failed. No data.")
elif action == "shutdown":
client.shutdownCoreServerSystem()
elif action == "reboot":
Expand Down
2 changes: 1 addition & 1 deletion awlsim-test
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ def run(inputFile):
if insnMeas:
if insnMeas.haveAnyMeasurements:
if opt_insnMeas == "-":
insnMeas.dump()
writeStdout(insnMeas.dump())
else:
with open(opt_insnMeas, "wb") as fd:
fd.write(insnMeas.dumpCSV().encode("UTF-8"))
Expand Down
13 changes: 9 additions & 4 deletions awlsim/core/cpu.py
Original file line number Diff line number Diff line change
Expand Up @@ -794,10 +794,15 @@ def reset(self):

self.initializeTimestamp()

def setupInsnMeas(self):
if not self.__insnMeas:
self.__insnMeas = InsnMeas()
return self.__insnMeas
def setupInsnMeas(self, enable=True):
if enable:
if not self.__insnMeas:
self.__insnMeas = InsnMeas()
insnMeas = self.__insnMeas
else:
insnMeas = self.__insnMeas
self.__insnMeas = None
return insnMeas

def setCycleExitCallback(self, cb, data=None):
self.cbCycleExit = cb
Expand Down
9 changes: 5 additions & 4 deletions awlsim/core/insnmeas.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,12 @@ def __allMeasData(self):
def dump(self):
if not self.haveAnyMeasurements:
return
printInfo("")
printInfo("Instruction time measurements:")
ret = []
ret.append("Instruction time measurements:")
for insnType, measData in self.__allMeasData:
name = AwlInsnTypes.type2name_german[insnType]
printInfo(measData.dump(name))
ret.append(measData.dump(name))
return "\n".join(ret) + "\n"

def dumpCSV(self):
if not self.haveAnyMeasurements:
Expand All @@ -149,4 +150,4 @@ def dumpCSV(self):
measData.minRt * 1.0e6,
measData.maxRt * 1.0e6,
measData.avgRt * 1.0e6))
return "\n".join(ret)
return "\n".join(ret) + "\n"
39 changes: 39 additions & 0 deletions awlsim/coreclient/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,45 @@ def getCpuStats(self, sync=False):
self.__send(msg)
return True

def measStart(self, sync=True):
"""Start instruction time measurements.
"""
if not self.__transceiver:
return None
msg = AwlSimMessage_MEAS_CONFIG(
flags=AwlSimMessage_MEAS_CONFIG.FLG_ENABLE)
if sync:
rxMsg = self.__sendAndWait(msg,
lambda rxMsg: (rxMsg.msgId == AwlSimMessage.MSG_ID_MEAS,
rxMsg.isReplyTo(msg)))
if rxMsg.flags & AwlSimMessage_MEAS.FLG_FAIL:
return False
else:
self.__send(msg)
return True

def measStop(self, csv=True, sync=True):
"""Stop instruction time measurements and
return the measurement report data string, if any.
"""
if not self.__transceiver:
return None
msg = AwlSimMessage_MEAS_CONFIG(
flags=AwlSimMessage_MEAS_CONFIG.FLG_GETMEAS)
if csv:
msg.flags |= AwlSimMessage_MEAS_CONFIG.FLG_CSV
if sync:
rxMsg = self.__sendAndWait(msg,
lambda rxMsg: (rxMsg.msgId == AwlSimMessage.MSG_ID_MEAS,
rxMsg.isReplyTo(msg)))
if ((rxMsg.flags & AwlSimMessage_MEAS.FLG_FAIL) or
not (rxMsg.flags & AwlSimMessage_MEAS.FLG_HAVEDATA)):
return ""
return rxMsg.reportStr
else:
self.__send(msg)
return ""

def shutdownCoreServer(self):
"""Shut down the core server.
"""
Expand Down
103 changes: 101 additions & 2 deletions awlsim/coreserver/messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ class AwlSimMessage(object):
MSG_ID_MEMORY = EnumGen.item
MSG_ID_INSNSTATE_CONFIG = EnumGen.item
MSG_ID_INSNSTATE = EnumGen.item
MSG_ID_MEAS_CONFIG = EnumGen.item
MSG_ID_MEAS = EnumGen.item
EnumGen.end

_bytesLenStruct = struct.Struct(str(">I"))
Expand Down Expand Up @@ -1299,6 +1301,101 @@ def fromBytes(cls, payload):
raise TransferError("INSNSTATE_CONFIG: Invalid data format")
return cls(flags, sourceId, fromLine, toLine, ob1Div, userData)

class AwlSimMessage_MEAS(AwlSimMessage):
msgId = AwlSimMessage.MSG_ID_MEAS

# Payload data struct:
# Flags (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# measurement report data (string)
plDataStruct = struct.Struct(str(">IIIIIIIIIIIIIIII"))

# Flags:
FLG_HAVEDATA = 1 << 0
FLG_FAIL = 1 << 1

def __init__(self, flags, reportStr):
self.flags = flags & 0xFFFFFFFF
self.reportStr = reportStr

def toBytes(self):
pl = self.plDataStruct.pack(self.flags,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
pl += self.packString(self.reportStr)
return AwlSimMessage.toBytes(self, len(pl)) + pl

@classmethod
def fromBytes(cls, payload):
try:
offset = 0
flags, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _ =\
cls.plDataStruct.unpack_from(payload, offset)
offset += cls.plDataStruct.size
reportStr, offset = cls.unpackString(payload, offset)
except (struct.error, IndexError) as e:
raise TransferError("MEAS: Invalid data format")
return cls(flags, reportStr)

class AwlSimMessage_MEAS_CONFIG(AwlSimMessage):
msgId = AwlSimMessage.MSG_ID_MEAS_CONFIG

# Payload data struct:
# Flags (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
# reserved (32 bit)
plDataStruct = struct.Struct(str(">IIIIIIIIIIIIIIII"))

# Flags:
FLG_ENABLE = 1 << 0
FLG_GETMEAS = 1 << 1
FLG_CSV = 1 << 2

def __init__(self, flags):
self.flags = flags & 0xFFFFFFFF

def toBytes(self):
pl = self.plDataStruct.pack(
self.flags,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
return AwlSimMessage.toBytes(self, len(pl)) + pl

@classmethod
def fromBytes(cls, payload):
try:
flags, _, _, _,\
_, _, _, _, _, _, _, _, _, _, _, _ =\
cls.plDataStruct.unpack_from(payload, 0)
except (struct.error, IndexError) as e:
raise TransferError("MEAS_CONFIG: Invalid data format")
return cls(flags)

class AwlSimMessage_REMOVESRC(AwlSimMessage):
msgId = AwlSimMessage.MSG_ID_REMOVESRC

Expand Down Expand Up @@ -1674,10 +1771,12 @@ class AwlSimMessageTransceiver(object):
AwlSimMessage.MSG_ID_CPUDUMP : AwlSimMessage_CPUDUMP,
AwlSimMessage.MSG_ID_REQ_MEMORY : AwlSimMessage_REQ_MEMORY,
AwlSimMessage.MSG_ID_MEMORY : AwlSimMessage_MEMORY,
AwlSimMessage.MSG_ID_INSNSTATE_CONFIG : AwlSimMessage_INSNSTATE_CONFIG,
AwlSimMessage.MSG_ID_INSNSTATE : AwlSimMessage_INSNSTATE,
AwlSimMessage.MSG_ID_GET_CPUSTATS : AwlSimMessage_GET_CPUSTATS,
AwlSimMessage.MSG_ID_CPUSTATS : AwlSimMessage_CPUSTATS,
AwlSimMessage.MSG_ID_INSNSTATE_CONFIG : AwlSimMessage_INSNSTATE_CONFIG,
AwlSimMessage.MSG_ID_INSNSTATE : AwlSimMessage_INSNSTATE,
AwlSimMessage.MSG_ID_MEAS_CONFIG : AwlSimMessage_MEAS_CONFIG,
AwlSimMessage.MSG_ID_MEAS : AwlSimMessage_MEAS,
}

DEFAULT_TX_BUF_SIZE = 1024 * 100
Expand Down
27 changes: 27 additions & 0 deletions awlsim/coreserver/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -1283,6 +1283,32 @@ def __rx_INSNSTATE_CONFIG(self, client, msg):
if msg.flags & msg.FLG_SYNC:
client.transceiver.send(AwlSimMessage_REPLY.make(msg, status))

def __rx_MEAS_CONFIG(self, client, msg):
printDebug("Received message: MEAS_CONFIG")
replyFlags = 0
replyStr = ""
insnMeas = None
if msg.flags & msg.FLG_ENABLE:
printDebug("Enabling instruction time measurements")
insnMeas = self.__sim.cpu.setupInsnMeas(True)
if not insnMeas:
replyFlags |= AwlSimMessage_MEAS.FLG_FAIL
else:
printDebug("Disabling instruction time measurements")
insnMeas = self.__sim.cpu.setupInsnMeas(False)
if msg.flags & msg.FLG_GETMEAS:
if insnMeas:
if msg.flags & msg.FLG_CSV:
replyStr = insnMeas.dumpCSV()
else:
replyStr = insnMeas.dump()
if replyStr:
replyFlags |= AwlSimMessage_MEAS.FLG_HAVEDATA
reply = AwlSimMessage_MEAS(flags=replyFlags,
reportStr=replyStr)
reply.setReplyTo(msg)
client.transceiver.send(reply)

def __rx_GET_IDENTS(self, client, msg):
printDebug("Received message: GET_IDENTS")
awlSrcs = symSrcs = hwMods = libSels = fupSrcs = kopSrcs = ()
Expand Down Expand Up @@ -1357,6 +1383,7 @@ def __rx_GET_CPUSTATS(self, client, msg):
AwlSimMessage.MSG_ID_REQ_MEMORY : (__rx_REQ_MEMORY, RXFLG_NONE),
AwlSimMessage.MSG_ID_MEMORY : (__rx_MEMORY, RXFLG_NONE),
AwlSimMessage.MSG_ID_INSNSTATE_CONFIG : (__rx_INSNSTATE_CONFIG, RXFLG_NONE),
AwlSimMessage.MSG_ID_MEAS_CONFIG : (__rx_MEAS_CONFIG, RXFLG_NONE),
AwlSimMessage.MSG_ID_GET_IDENTS : (__rx_GET_IDENTS, RXFLG_NONE),
# AwlSimMessage.MSG_ID_GET_CPUDUMP : (__rx_GET_CPUDUMP, RXFLG_NONE),
AwlSimMessage.MSG_ID_GET_CPUSTATS : (__rx_GET_CPUSTATS, RXFLG_NONE),
Expand Down

0 comments on commit ccef7e1

Please sign in to comment.