2
0
forked from Ivasoft/DSView
This commit is contained in:
DreamSourceLab
2020-05-09 14:57:00 +08:00

View File

@@ -3,6 +3,7 @@
##
## Copyright (C) 2012-2013 Uwe Hermann <uwe@hermann-uwe.de>
## Copyright (C) 2019 DreamSourceLab <support@dreamsourcelab.com>
## Copyright (C) 2020 Raptor Engineering, LLC <support@raptorengineering.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
@@ -62,6 +63,26 @@ fields = {
0b1110: 'Reserved / not allowed',
0b1111: 'Reserved / not allowed',
},
# Cycle type / direction field
# False for read cycle, True for write cycle
'CT_DR_WR': {
0b0000: False,
0b0001: False,
0b0010: True,
0b0011: True,
0b0100: False,
0b0101: False,
0b0110: True,
0b0111: True,
0b1000: False,
0b1001: False,
0b1010: True,
0b1011: True,
0b1100: False,
0b1101: False,
0b1110: False,
0b1111: False,
},
# SIZE field (determines how many bytes are to be transferred)
# Bits[3:2] are reserved, must be driven to 0b00.
# Neither host nor peripheral are allowed to drive 0b0010.
@@ -155,11 +176,13 @@ class Decoder(srd.Decoder):
self.samplenum = 0
self.lad = -1
self.addr = 0
self.direction = 0
self.cur_nibble = 0
self.cycle_type = -1
self.databyte = 0
self.tarcount = 0
self.synccount = 0
self.timeoutcount = 0
self.oldpins = None
self.ss_block = self.es_block = None
@@ -189,6 +212,13 @@ class Decoder(srd.Decoder):
if (self.oldlad == 0b0000 or self.oldlad == 0b0101):
self.start_field = self.oldlad
self.state = 'GET CT/DR'
elif (self.oldlad == 0b1101 or self.oldlad == 0b1110):
self.start_field = self.oldlad
if (self.oldlad == 0b1110):
self.direction = True
else:
self.direction = False
self.state = 'GET FW IDSEL'
else:
self.state = 'IDLE'
@@ -196,6 +226,7 @@ class Decoder(srd.Decoder):
# LAD[3:0]: Cycle type / direction field (1 clock cycle).
self.cycle_type = fields['CT_DR'][self.oldlad]
self.direction = fields['CT_DR_WR'][self.oldlad]
# TODO: Warning/error on invalid cycle types.
if self.cycle_type == 'Reserved':
@@ -209,6 +240,58 @@ class Decoder(srd.Decoder):
self.addr = 0
self.cur_nibble = 0
def handle_get_fw_idsel(self):
# LAD[3:0]: IDSEL field (1 clock cycle).
self.es_block = self.samplenum
s = 'IDSEL: 0x%%0%dx' % self.oldlad
self.putb([3, [s % self.oldlad]])
self.ss_block = self.samplenum
self.state = 'GET FW ADDR'
self.addr = 0
self.cur_nibble = 0
def handle_get_fw_addr(self):
# LAD[3:0]: ADDR field (7 clock cycles).
addr_nibbles = 7 # Address is 28bits.
# Addresses are driven MSN-first.
offset = ((addr_nibbles - 1) - self.cur_nibble) * 4
if (offset < 0):
self.putb([0, ['Warning: Invalid address shift: %d' % offset]])
self.state = 'IDLE'
return
self.addr |= (self.oldlad << offset)
# Continue if we haven't seen all ADDR cycles, yet.
if (self.cur_nibble < addr_nibbles - 1):
self.cur_nibble += 1
return
self.es_block = self.samplenum
s = 'Address: 0x%%0%dx' % addr_nibbles
self.putb([3, [s % self.addr]])
self.ss_block = self.samplenum
self.state = 'GET FW MSIZE'
def handle_get_fw_msize(self):
# LAD[3:0]: MSIZE field (1 clock cycle).
self.es_block = self.samplenum
s = 'MSIZE: 0x%%0%dx' % self.oldlad
self.putb([3, [s % self.oldlad]])
self.ss_block = self.samplenum
self.msize = self.oldlad
if self.direction == 1:
self.state = 'GET FW DATA'
self.cycle_count = 0
self.dataword = 0
self.cur_nibble = 0
else:
self.state = 'GET TAR'
self.tar_count = 0
def handle_get_addr(self):
# LAD[3:0]: ADDR field (4/8/0 clock cycles).
@@ -223,6 +306,10 @@ class Decoder(srd.Decoder):
# Addresses are driven MSN-first.
offset = ((addr_nibbles - 1) - self.cur_nibble) * 4
if (offset < 0):
self.putb([0, ['Warning: Invalid address shift: %d' % offset]])
self.state = 'IDLE'
return
self.addr |= (self.oldlad << offset)
# Continue if we haven't seen all ADDR cycles, yet.
@@ -235,8 +322,12 @@ class Decoder(srd.Decoder):
self.putb([3, [s % self.addr]])
self.ss_block = self.samplenum
self.state = 'GET TAR'
self.tar_count = 0
if self.direction == 1:
self.state = 'GET DATA'
self.cycle_count = 0
else:
self.state = 'GET TAR'
self.tar_count = 0
def handle_get_tar(self):
# LAD[3:0]: First TAR (turn-around) field (2 clock cycles).
@@ -277,12 +368,17 @@ class Decoder(srd.Decoder):
self.ss_block = self.samplenum
# TODO
self.cycle_count = 0
if (lframe == 0):
self.state = 'GET TIMEOUT'
else:
self.state = 'GET DATA'
if (self.cycle_type != 'Short wait' and self.cycle_type != 'Long wait'):
self.cycle_count = 0
if (lframe == 0):
self.state = 'GET TIMEOUT'
elif (self.start_field == 0b1101 or self.start_field == 0b1110):
self.state = 'GET FW DATA'
self.cycle_count = 0
self.dataword = 0
self.cur_nibble = 0
else:
self.state = 'GET DATA'
def handle_get_timeout(self):
# LFRAME#: tie low (4 clock cycles).
@@ -303,6 +399,50 @@ class Decoder(srd.Decoder):
self.timeoutcount = 0
self.state = 'IDLE'
def handle_get_fw_data(self):
# LAD[3:0]: DATA field
if (self.msize == 0b0000):
data_nibbles = 2 # Data is 8bits.
elif (self.msize == 0b0001):
data_nibbles = 4 # Data is 16bits.
elif (self.msize == 0b0010):
data_nibbles = 8 # Data is 32bits.
elif (self.msize == 0b0100):
data_nibbles = 32 # Data is 128bits.
elif (self.msize == 0b0111):
data_nibbles = 256 # Data is 1024bits.
else:
self.putb([0, ['Warning: Invalid MSIZE: %d' % self.msize]])
self.state = 'IDLE'
return
# Data is driven LSN-first.
nibble_swap = self.cur_nibble % 2
offset = ((data_nibbles - 1) - self.cur_nibble) * 4
if (nibble_swap):
offset += 4
else:
offset -= 4
if (offset < 0):
self.putb([0, ['Warning: Invalid data shift: %d' % offset]])
self.state = 'IDLE'
return
self.dataword |= (self.oldlad << offset)
# Continue if we haven't seen all DATA cycles, yet.
if (self.cur_nibble < data_nibbles - 1):
self.cur_nibble += 1
return
self.es_block = self.samplenum
s = 'DATA: 0x%%0%dx' % data_nibbles
self.putb([3, [s % self.dataword]])
self.ss_block = self.samplenum
self.cycle_count = 0
self.state = 'GET TAR2'
def handle_get_data(self):
# LAD[3:0]: DATA field (2 clock cycles).
@@ -312,7 +452,9 @@ class Decoder(srd.Decoder):
elif (self.cycle_count == 1):
self.databyte |= (self.oldlad << 4)
else:
raise Exception('Invalid cycle_count: %d' % self.cycle_count)
self.putb([0, ['Warning: Invalid cycle_count: %d' % self.cycle_count]])
self.state = 'IDLE'
return
if (self.cycle_count != 1):
self.cycle_count += 1
@@ -362,6 +504,10 @@ class Decoder(srd.Decoder):
# TODO: Only memory read/write is currently supported/tested.
# Detect host cycle abort requests
if (lframe == 0) and (self.oldlframe == 0):
self.state = 'GET TIMEOUT'
# State machine
if self.state == 'IDLE':
# A valid LPC cycle starts with LFRAME# being asserted (low).
@@ -377,12 +523,20 @@ class Decoder(srd.Decoder):
self.handle_get_ct_dr()
elif self.state == 'GET ADDR':
self.handle_get_addr()
elif self.state == 'GET FW IDSEL':
self.handle_get_fw_idsel()
elif self.state == 'GET FW ADDR':
self.handle_get_fw_addr()
elif self.state == 'GET FW MSIZE':
self.handle_get_fw_msize()
elif self.state == 'GET TAR':
self.handle_get_tar()
elif self.state == 'GET SYNC':
self.handle_get_sync(lframe)
elif self.state == 'GET TIMEOUT':
self.handle_get_timeout()
elif self.state == 'GET FW DATA':
self.handle_get_fw_data()
elif self.state == 'GET DATA':
self.handle_get_data()
elif self.state == 'GET TAR2':