fix: avr pdi decoding is error

This commit is contained in:
dreamsourcelabTAI 2023-12-27 10:37:19 +08:00
parent 735a8b5933
commit 12cec54159

View File

@ -86,6 +86,7 @@ class Ann:
BIN_BYTES, BIN_BYTES,
) = range(1) ) = range(1)
#元组
Bit = namedtuple('Bit', 'val ss es') Bit = namedtuple('Bit', 'val ss es')
class PDI: class PDI:
@ -175,10 +176,14 @@ class Decoder(srd.Decoder):
self.break_es = None self.break_es = None
self.clear_insn() self.clear_insn()
def clear_insn(self): def clear_insn(self):
# Collect instructions and their arguments, # Collect instructions and their arguments,
# properties of the current instructions. # properties of the current instructions.
self.insn_rep_count = 0 self.insn_rep_count = 0
self.insn_opcode = None self.insn_opcode = None
self.insn_wr_counts = [] self.insn_wr_counts = []
self.insn_rd_counts = [] self.insn_rd_counts = []
@ -191,6 +196,17 @@ class Decoder(srd.Decoder):
self.cmd_insn_parts_nice = [] self.cmd_insn_parts_nice = []
self.cmd_insn_parts_terse = [] self.cmd_insn_parts_terse = []
#new
self.insn_write_counts = 0
self.insn_read_counts = 0
self.width_addr = 0
self.width_data = 0
self.ptr_txt = None
self.ptr_txt_terse = None
self.reg_num = None
self.reg_txt = None
self.reg_txt_terse = None
def metadata(self, key, value): def metadata(self, key, value):
if key == srd.SRD_CONF_SAMPLERATE: if key == srd.SRD_CONF_SAMPLERATE:
self.samplerate = value self.samplerate = value
@ -218,6 +234,7 @@ class Decoder(srd.Decoder):
# Handle BREAK conditions, which will abort any # Handle BREAK conditions, which will abort any
# potentially currently executing instruction. # potentially currently executing instruction.
is_break = byteval is None is_break = byteval is None
if is_break: if is_break:
self.cmd_insn_parts_nice.append('BREAK') self.cmd_insn_parts_nice.append('BREAK')
@ -227,6 +244,7 @@ class Decoder(srd.Decoder):
# Decode instruction opcodes and argument sizes # Decode instruction opcodes and argument sizes
# from the first byte of a transaction. # from the first byte of a transaction.
if self.insn_opcode is None and not is_break: if self.insn_opcode is None and not is_break:
opcode = (byteval & 0xe0) >> 5 opcode = (byteval & 0xe0) >> 5
arg30 = byteval & 0x0f arg30 = byteval & 0x0f
@ -238,112 +256,137 @@ class Decoder(srd.Decoder):
if opcode == PDI.OP_LDS: if opcode == PDI.OP_LDS:
# LDS: load data, direct addressing. # LDS: load data, direct addressing.
# Writes an address, reads a data item. # Writes an address, reads a data item.
width_addr = arg32 + 1
width_data = arg10 + 1 self.width_addr = arg32 + 1
self.insn_wr_counts = [width_addr] self.width_data = arg10 + 1
self.insn_rd_counts = [width_data]
self.insn_write_counts = 1
self.insn_read_counts = 1
mnemonics = [ mnemonics = [
'Insn: LDS a{:d}, m{:d}'.format(width_addr, width_data), 'Insn: LDS a{:d}, m{:d}'.format(self.width_addr, self.width_data),
'LDS a{:d}, m{:d}'.format(width_addr, width_data), 'LDS', 'LDS a{:d}, m{:d}'.format(self.width_addr, self.width_data), 'LDS',
] ]
self.cmd_insn_parts_nice = ['LDS'] self.cmd_insn_parts_nice = ['LDS']
self.cmd_insn_parts_terse = ['LDS'] self.cmd_insn_parts_terse = ['LDS']
elif opcode == PDI.OP_LD: elif opcode == PDI.OP_LD:
# LD: load data, indirect addressing. # LD: load data, indirect addressing.
# Reads a data item, with optional repeat. # Reads a data item, with optional repeat.
ptr_txt = PDI.pointer_format_nice[arg32]
ptr_txt_terse = PDI.pointer_format_terse[arg32] self.ptr_txt = PDI.pointer_format_nice[arg32]
width_data = arg10 + 1 self.ptr_txt_terse = PDI.pointer_format_terse[arg32]
self.insn_wr_counts = []
self.insn_rd_counts = [width_data] self.width_data = arg10 + 1
self.insn_write_counts = 0
self.insn_read_counts = 1
if self.insn_rep_count: if self.insn_rep_count:
self.insn_rd_counts.extend(self.insn_rep_count * [width_data]) self.insn_read_counts = self.insn_rep_count * self.insn_read_counts
self.insn_rep_count = 0 self.insn_rep_count = 0
mnemonics = [ mnemonics = [
'Insn: LD {:s} m{:d}'.format(ptr_txt, width_data), 'Insn: LD {:s} m{:d}'.format(self.ptr_txt, self.width_data),
'LD {:s} m{:d}'.format(ptr_txt, width_data), 'LD', 'LD {:s} m{:d}'.format(self.ptr_txt, self.width_data), 'LD',
] ]
self.cmd_insn_parts_nice = ['LD', ptr_txt] self.cmd_insn_parts_nice = ['LD', self.ptr_txt]
self.cmd_insn_parts_terse = ['LD', ptr_txt_terse] self.cmd_insn_parts_terse = ['LD', self.ptr_txt_terse]
elif opcode == PDI.OP_STS: elif opcode == PDI.OP_STS:
# STS: store data, direct addressing. # STS: store data, direct addressing.
# Writes an address, writes a data item. # Writes an address, writes a data item.
width_addr = arg32 + 1 self.width_addr = arg32 + 1
width_data = arg10 + 1 self.width_data = arg10 + 1
self.insn_wr_counts = [width_addr, width_data]
self.insn_rd_counts = [] self.insn_write_counts = 2
self.insn_read_counts = 0
mnemonics = [ mnemonics = [
'Insn: STS a{:d}, i{:d}'.format(width_addr, width_data), 'Insn: STS a{:d}, i{:d}'.format(self.width_addr, self.width_data),
'STS a{:d}, i{:d}'.format(width_addr, width_data), 'STS', 'STS a{:d}, i{:d}'.format(self.width_addr, self.width_data), 'STS',
] ]
self.cmd_insn_parts_nice = ['STS'] self.cmd_insn_parts_nice = ['STS']
self.cmd_insn_parts_terse = ['STS'] self.cmd_insn_parts_terse = ['STS']
elif opcode == PDI.OP_ST: elif opcode == PDI.OP_ST:
# ST: store data, indirect addressing. # ST: store data, indirect addressing.
# Writes a data item, with optional repeat. # Writes a data item, with optional repeat.
ptr_txt = PDI.pointer_format_nice[arg32] self.ptr_txt = PDI.pointer_format_nice[arg32]
ptr_txt_terse = PDI.pointer_format_terse[arg32] self.ptr_txt_terse = PDI.pointer_format_terse[arg32]
width_data = arg10 + 1
self.insn_wr_counts = [width_data] self.width_data = arg10 + 1
self.insn_rd_counts = []
self.insn_write_counts = 1
self.insn_read_counts = 0
if self.insn_rep_count: if self.insn_rep_count:
self.insn_wr_counts.extend(self.insn_rep_count * [width_data]) self.insn_write_counts = self.insn_rep_count * self.insn_write_counts
self.insn_rep_count = 0 self.insn_rep_count = 0
mnemonics = [ mnemonics = [
'Insn: ST {:s} i{:d}'.format(ptr_txt, width_data), 'Insn: ST {:s} i{:d}'.format(self.ptr_txt, self.width_data),
'ST {:s} i{:d}'.format(ptr_txt, width_data), 'ST', 'ST {:s} i{:d}'.format(self.ptr_txt, self.width_data), 'ST',
] ]
self.cmd_insn_parts_nice = ['ST', ptr_txt] self.cmd_insn_parts_nice = ['ST', self.ptr_txt]
self.cmd_insn_parts_terse = ['ST', ptr_txt_terse] self.cmd_insn_parts_terse = ['ST', self.ptr_txt_terse]
elif opcode == PDI.OP_LDCS: elif opcode == PDI.OP_LDCS:
# LDCS: load control/status. # LDCS: load control/status.
# Loads exactly one byte. # Loads exactly one byte.
reg_num = arg30
reg_txt = PDI.ctrl_reg_name.get(reg_num, 'r{:d}'.format(reg_num)) self.reg_num = arg30
reg_txt_terse = '{:d}'.format(reg_num) self.reg_txt = PDI.ctrl_reg_name.get(self.reg_num, 'r{:d}'.format(self.reg_num))
self.insn_wr_counts = [] self.reg_txt_terse = '{:d}'.format(self.reg_num)
self.insn_rd_counts = [1]
self.insn_write_counts = 0
self.insn_read_counts = 1
self.width_data = 1
mnemonics = [ mnemonics = [
'Insn: LDCS {:s}, m1'.format(reg_txt), 'Insn: LDCS {:s}, m1'.format(self.reg_txt),
'LDCS {:s}, m1'.format(reg_txt), 'LDCS', 'LDCS {:s}, m1'.format(self.reg_txt), 'LDCS',
] ]
self.cmd_insn_parts_nice = ['LDCS', reg_txt] self.cmd_insn_parts_nice = ['LDCS', self.reg_txt]
self.cmd_insn_parts_terse = ['LDCS', reg_txt_terse] self.cmd_insn_parts_terse = ['LDCS', self.reg_txt_terse]
elif opcode == PDI.OP_STCS: elif opcode == PDI.OP_STCS:
# STCS: store control/status. # STCS: store control/status.
# Writes exactly one byte. # Writes exactly one byte.
reg_num = arg30
reg_txt = PDI.ctrl_reg_name.get(reg_num, 'r{:d}'.format(reg_num)) self.reg_num = arg30
reg_txt_terse = '{:d}'.format(reg_num) self.reg_txt = PDI.ctrl_reg_name.get(self.reg_num, 'r{:d}'.format(self.reg_num))
self.insn_wr_counts = [1] self.reg_txt_terse = '{:d}'.format(self.reg_num)
self.insn_rd_counts = []
self.width_data = 1
self.insn_write_counts = 1
self.insn_read_counts = 0
mnemonics = [ mnemonics = [
'Insn: STCS {:s}, i1'.format(reg_txt), 'Insn: STCS {:s}, i1'.format(self.reg_txt),
'STCS {:s}, i1'.format(reg_txt), 'STCS', 'STCS {:s}, i1'.format(self.reg_txt), 'STCS',
] ]
self.cmd_insn_parts_nice = ['STCS', reg_txt] self.cmd_insn_parts_nice = ['STCS', self.reg_txt]
self.cmd_insn_parts_terse = ['STCS', reg_txt_terse] self.cmd_insn_parts_terse = ['STCS', self.reg_txt_terse]
elif opcode == PDI.OP_REPEAT: elif opcode == PDI.OP_REPEAT:
# REPEAT: sets repeat count for the next instruction. # REPEAT: sets repeat count for the next instruction.
# Reads repeat count from following bytes. # Reads repeat count from following bytes.
width_data = arg10 + 1 self.width_data = arg10 + 1
self.insn_wr_counts = [width_data]
self.insn_rd_counts = [] self.insn_write_counts = 1
self.insn_read_counts = 0
mnemonics = [ mnemonics = [
'Insn: REPEAT i{:d}'.format(width_data), 'Insn: REPEAT i{:d}'.format(self.width_data),
'REPEAT i{:d}'.format(width_data), 'REP', 'REPEAT i{:d}'.format(self.width_data), 'REP',
] ]
self.cmd_insn_parts_nice = ['REPEAT'] self.cmd_insn_parts_nice = ['REPEAT']
self.cmd_insn_parts_terse = ['REP'] self.cmd_insn_parts_terse = ['REP']
elif opcode == PDI.OP_KEY: elif opcode == PDI.OP_KEY:
# KEY: set activation key (enables PDIBUS mmap access). # KEY: set activation key (enables PDIBUS mmap access).
# Writes a sequence of 8 bytes, fixed length. # Writes a sequence of 8 bytes, fixed length.
width_data = 8
self.insn_wr_counts = [width_data] self.width_data = 8
self.insn_rd_counts = []
mnemonics = [ mnemonics = [
'Insn: KEY i{:d}'.format(width_data), 'Insn: KEY i{:d}'.format(self.width_data),
'KEY i{:d}'.format(width_data), 'KEY', 'KEY i{:d}'.format(self.width_data), 'KEY',
] ]
self.cmd_insn_parts_nice = ['KEY'] self.cmd_insn_parts_nice = ['KEY']
self.cmd_insn_parts_terse = ['KEY'] self.cmd_insn_parts_terse = ['KEY']
@ -353,12 +396,33 @@ class Decoder(srd.Decoder):
# Prepare to write/read operands/data bytes. # Prepare to write/read operands/data bytes.
self.insn_dat_bytes = [] self.insn_dat_bytes = []
if self.insn_wr_counts:
self.insn_dat_count = self.insn_wr_counts[0] if self.insn_write_counts != 0:
if self.insn_opcode == PDI.OP_LDS:
self.insn_dat_count = self.width_addr
elif self.insn_opcode == PDI.OP_STS:
if self.insn_write_counts == 2:
self.insn_dat_count = self.width_addr
elif self.insn_write_counts == 1:
self.insn_dat_count = self.width_data
elif self.insn_opcode == PDI.OP_ST:
self.insn_dat_count = self.width_data
elif opcode == PDI.OP_STCS:
self.insn_dat_count = self.width_data
elif opcode == PDI.OP_REPEAT:
self.insn_dat_count = self.width_data
elif opcode == PDI.OP_KEY:
self.insn_dat_count = self.width_data
return return
if self.insn_rd_counts: if self.insn_read_counts != 0:
self.insn_dat_count = self.insn_rd_counts[0] if self.insn_opcode == PDI.OP_LDS:
self.insn_dat_count = self.width_data
elif self.insn_opcode == PDI.OP_LD:
self.insn_dat_count = self.width_data
elif self.insn_opcode == PDI.OP_LDCS:
self.insn_dat_count = self.width_data
return return
# FALLTHROUGH. # FALLTHROUGH.
# When there are no operands or data bytes to read, # When there are no operands or data bytes to read,
# then fall through to the end of the instruction # then fall through to the end of the instruction
@ -366,6 +430,7 @@ class Decoder(srd.Decoder):
# Read bytes which carry operands (addresses, immediates) # Read bytes which carry operands (addresses, immediates)
# or data values for memory access. # or data values for memory access.
if self.insn_dat_count and not is_break: if self.insn_dat_count and not is_break:
# Accumulate received bytes until another multi byte # Accumulate received bytes until another multi byte
@ -373,6 +438,7 @@ class Decoder(srd.Decoder):
if not self.insn_dat_bytes: if not self.insn_dat_bytes:
self.insn_ss_data = ss self.insn_ss_data = ss
self.insn_dat_bytes.append(byteval) self.insn_dat_bytes.append(byteval)
self.insn_dat_count -= 1 self.insn_dat_count -= 1
if self.insn_dat_count: if self.insn_dat_count:
return return
@ -381,16 +447,17 @@ class Decoder(srd.Decoder):
# "consume" its length spec (to simplify later steps). # "consume" its length spec (to simplify later steps).
data_ss = self.insn_ss_data data_ss = self.insn_ss_data
data_es = es data_es = es
if self.insn_wr_counts: if self.insn_write_counts != 0:
data_ann = Ann.DATA_PROG data_ann = Ann.DATA_PROG
data_width = self.insn_wr_counts.pop(0) self.insn_write_counts = self.insn_write_counts - 1
elif self.insn_rd_counts: elif self.insn_read_counts != 0:
data_ann = Ann.DATA_DEV data_ann = Ann.DATA_DEV
data_width = self.insn_rd_counts.pop(0) self.insn_read_counts = self.insn_read_counts - 1
# PDI communicates multi-byte data items in little endian # PDI communicates multi-byte data items in little endian
# order. Get a nice textual representation of the number, # order. Get a nice textual representation of the number,
# wide and narrow for several zoom levels. # wide and narrow for several zoom levels.
self.insn_dat_bytes.reverse() self.insn_dat_bytes.reverse()
data_txt_digits = ''.join(['{:02x}'.format(b) for b in self.insn_dat_bytes]) data_txt_digits = ''.join(['{:02x}'.format(b) for b in self.insn_dat_bytes])
data_txt_hex = '0x' + data_txt_digits data_txt_hex = '0x' + data_txt_digits
@ -407,19 +474,40 @@ class Decoder(srd.Decoder):
self.cmd_insn_parts_nice.append(data_txt_hex) self.cmd_insn_parts_nice.append(data_txt_hex)
self.cmd_insn_parts_terse.append(data_txt_digits) self.cmd_insn_parts_terse.append(data_txt_digits)
# Send out write data first until exhausted, if self.insn_write_counts != 0:
# then drain expected read data. if self.insn_opcode == PDI.OP_LDS:
if self.insn_wr_counts: self.insn_dat_count = self.width_addr
self.insn_dat_count = self.insn_wr_counts[0] elif self.insn_opcode == PDI.OP_STS:
if self.insn_write_counts == 2:
self.insn_dat_count = self.width_addr
elif self.insn_write_counts == 1:
self.insn_dat_count = self.width_data
elif self.insn_opcode == PDI.OP_ST:
self.insn_dat_count = self.width_data
elif opcode == PDI.OP_STCS:
self.insn_dat_count = self.width_data
elif opcode == PDI.OP_REPEAT:
self.insn_dat_count = self.width_data
elif opcode == PDI.OP_KEY:
self.insn_dat_count = self.width_data
return return
if self.insn_rd_counts: if self.insn_read_counts != 0:
self.insn_dat_count = self.insn_rd_counts[0] if self.insn_opcode == PDI.OP_LDS:
self.insn_dat_count = self.width_data
elif self.insn_opcode == PDI.OP_LD:
self.insn_dat_count = self.width_data
elif self.insn_opcode == PDI.OP_LDCS:
self.insn_dat_count = self.width_data
return return
# FALLTHROUGH. # FALLTHROUGH.
# When all operands and data bytes were seen, # When all operands and data bytes were seen,
# terminate the inspection of the instruction. # terminate the inspection of the instruction.
if self.cmd_ss == None:
self.printlog("self.cmd_ss is null")
return
# Postprocess the instruction after its operands were seen. # Postprocess the instruction after its operands were seen.
cmd_es = es cmd_es = es
cmd_txt_nice = ' '.join(self.cmd_insn_parts_nice) cmd_txt_nice = ' '.join(self.cmd_insn_parts_nice)
@ -481,10 +569,16 @@ class Decoder(srd.Decoder):
# after the line went idle (high) again. Pass BREAK to the upper layer # after the line went idle (high) again. Pass BREAK to the upper layer
# as well. When the line is low, BREAK still is pending. When the line # as well. When the line is low, BREAK still is pending. When the line
# is high, the current bit cannot be START, thus return from here. # is high, the current bit cannot be START, thus return from here.
if self.break_ss is not None: if self.break_ss is not None:
if bitval == '0': if bitval == 0:
self.break_es = es self.break_es = es
return return
if self.break_es == None:
self.printlog("self.break_es is null.")
return
self.put(self.break_ss, self.break_es, self.out_ann, self.put(self.break_ss, self.break_es, self.out_ann,
[Ann.BREAK, ann_class_text[Ann.BREAK]]) [Ann.BREAK, ann_class_text[Ann.BREAK]])
self.handle_byte(self.break_ss, self.break_es, None) self.handle_byte(self.break_ss, self.break_es, None)
@ -573,4 +667,4 @@ class Decoder(srd.Decoder):
def decode(self): def decode(self):
while True: while True:
(clock_pin, data_pin) = self.wait({0: 'e'}) (clock_pin, data_pin) = self.wait({0: 'e'})
self.handle_clk_edge(clock_pin, data_pin) self.handle_clk_edge(clock_pin, data_pin)