diff options
Diffstat (limited to 'src/csview.vala')
-rw-r--r-- | src/csview.vala | 540 |
1 files changed, 540 insertions, 0 deletions
diff --git a/src/csview.vala b/src/csview.vala new file mode 100644 index 0000000..0a2cc24 --- /dev/null +++ b/src/csview.vala @@ -0,0 +1,540 @@ +using Gtk; +using Emulation; + +namespace GUI +{ + public class CSListModel : GLib.Object, TreeModel + { + public enum Columns + { + NAME = 0, + VALUE, + TARGET, + COUNT + } + + public enum RowType + { + PACKET = 0, + HEADER, + DWORD, + BITFIELD, + HEADER_BITFIELD + } + + private static string[] packet_strings = { + "packet0", + "packet1", + "packet2", + "packet3" + }; + + private static string[] packet0_headers = { + "BASE_INDEX", + "ONE_REG_WR", + "COUNT", + "TYPE" + }; + + private static string[] packet1_headers = { + "REG_INDEX1", + "REG_INDEX2", + "TYPE" + }; + + private static string[] packet2_headers = { + "TYPE" + }; + + private static string[] packet3_headers = { + "IT_OPCODE", + "COUNT", + "TYPE" + }; + + private static string[][] packet_headers = { + packet0_headers, + packet1_headers, + packet2_headers, + packet3_headers + }; + + private static uint[] packet_headers_length = { 4, 3, 1, 3 }; + + public inline uint get_packet_num(TreeIter iter) { return *((uint*)(&iter.user_data)); } + private inline uint get_dword_num(TreeIter iter) { return *((uint*)(&iter.user_data2)); } + private inline uint get_bitfield_num(TreeIter iter) { return *((uint*)(&iter.user_data3)); } + + private inline void set_packet_num(ref TreeIter iter, uint n) { iter.user_data = *((void**)(&n)); } + private inline void set_dword_num(ref TreeIter iter, uint n) { iter.user_data2 = *((void**)(&n)); } + private inline void set_bitfield_num(ref TreeIter iter, uint n) { iter.user_data3 = *((void**)(&n)); } + + /* for dwords, 0 means no dwords, 1 means just the header, and 2+ means header and packets */ + /* for bitfields, 0 means no bitfields, 1+ means bitfields */ + + private inline bool is_header(TreeIter iter) { return get_dword_num(iter) == 1; } + private inline bool has_dwords(TreeIter iter) { return get_dword_num(iter) >= 1; } + private inline bool has_bitfields(TreeIter iter) { return get_bitfield_num(iter) >= 1; } + + private inline uint dword_index(TreeIter iter) { return get_dword_num(iter) - 2; } + private inline uint bitfield_index(TreeIter iter) { return get_bitfield_num(iter) - 1; } + + private inline void set_iter(ref TreeIter iter, uint p, uint d, uint b, bool stamp = true) + { + set_packet_num(ref iter, p); + set_dword_num(ref iter, d); + set_bitfield_num(ref iter, b); + iter.stamp = (stamp) ? m_stamp : 0; + } + + private CS m_cs; + private Spec m_spec; + private int m_stamp; + + public CSListModel(CS cs, Spec spec) + { + m_cs = cs; + m_spec = spec; + m_stamp = 19449216; + } + + public RowType get_row_type(TreeIter iter) + { + if (has_bitfields(iter)) { + return is_header(iter) ? RowType.HEADER_BITFIELD : RowType.BITFIELD; + } else if (has_dwords(iter)) { + return is_header(iter) ? RowType.HEADER : RowType.DWORD; + } + + return RowType.PACKET; + } + + public TreeModelFlags get_flags() + { + return TreeModelFlags.ITERS_PERSIST; + } + + public int get_n_columns() + { + return Columns.COUNT; + } + + public Type get_column_type(int i) + { + return typeof(string); + } + + public bool get_iter(out TreeIter iter, TreePath path) + { + var depth = path.get_depth(); + assert(depth <= 3 && depth >= 1); + + int *indices = path.get_indices(); + + if (indices[0] >= m_cs.packets.length || indices[0] < 0) { return false; } + set_iter(ref iter, indices[0], 0, 0, false); + + if (depth >= 2) { + if (indices[1] > m_cs.packets[indices[0]].length || indices[1] < 0) { return false; } + set_dword_num(ref iter, indices[1]+1); + } + + if (depth >= 3) { + if (indices[2] < 0) { return false; } + if (indices[1] == 0) { + /* Header */ + if (indices[2] >= packet_headers_length[m_cs.packets[indices[0]].type_id]) { return false; } + } else { + /* XXX: DWORD */ + return false; + } + set_bitfield_num(ref iter, indices[2]+1); + } + + iter.stamp = m_stamp; + + return true; + } + + public TreePath get_path(TreeIter iter) + { + var path = new TreePath(); + + path.append_index((int)get_packet_num(iter)); + if (has_dwords(iter)) { path.append_index((int)get_dword_num(iter) - 1); } + if (has_bitfields(iter)) { path.append_index((int)get_bitfield_num(iter) - 1); } + + return path; + } + + public uint32 get_numeric_value(TreeIter iter) + { + PacketBase p = m_cs.packets[get_packet_num(iter)]; + switch (get_row_type(iter)) { + case RowType.PACKET: return p.header; + case RowType.DWORD: return p[dword_index(iter)]; + case RowType.HEADER: return p.header; + + case RowType.BITFIELD: + /* TODO */ + break; + + case RowType.HEADER_BITFIELD: + switch (p.type_id) { + case 0: + Packet0 p0 = p as Packet0; + switch (bitfield_index(iter)) { + case 0: return p0._ADDR; + case 1: return p0._ONE_REG_WR; + case 2: return p0._COUNT; + case 3: return p.type_id; + } + break; + + case 1: + Packet1 p1 = p as Packet1; + switch (bitfield_index(iter)) { + case 0: return p1._ADDR1; + case 1: return p1._ADDR2; + case 2: return p.type_id; + } + break; + + case 2: + switch (bitfield_index(iter)) { + case 0: return p.type_id; + } + break; + + case 3: + Packet3 p3 = p as Packet3; + switch (bitfield_index(iter)) { + case 0: return p3._IT_OPCODE; + case 1: return p3._COUNT; + case 2: return p.type_id; + } + break; + } + break; + } + + return 0; + } + + private string translate_addr(uint32 addr) + { + var regs = m_spec.translate_addr((uint)addr); + if (regs == null) { return addr.to_string("0x%04X"); } + return regs[0].info.name; + } + + public void get_value(TreeIter iter, int column, out Value val) + { + PacketBase p = m_cs.packets[get_packet_num(iter)]; + val.init(typeof(string)); + + switch (get_row_type(iter)) { + case RowType.PACKET: + switch (column) { + case Columns.NAME: val.set_static_string(packet_strings[p.type_id]); break; + case Columns.VALUE: val.set_string(p.header.to_string("0x%08X")); break; + case Columns.TARGET: + switch (p.type_id) { + case 0: val.set_string(translate_addr((p as Packet0).addr)); break; + case 1: val.set_string(translate_addr((p as Packet1).addr1) + " | " + translate_addr((p as Packet1).addr2)); break; + case 2: val.set_static_string(""); break; + case 3: val.set_static_string("TODO"); break; + } + break; + } + break; + + case RowType.DWORD: + switch (column) { + case Columns.NAME: val.set_string(dword_index(iter).to_string("DWORD%u")); break; + case Columns.VALUE: val.set_string(p[dword_index(iter)].to_string("0x%08X")); break; + case Columns.TARGET: + switch (p.type_id) { + case 0: val.set_string(translate_addr((p as Packet0).addr + 4*dword_index(iter)*((p as Packet0).one_reg_wr ? 0 : 1))); break; + case 1: val.set_string(translate_addr((dword_index(iter) == 0) ? (p as Packet1).addr1 : (p as Packet1).addr2)); break; + case 2: val.set_static_string(""); break; + case 3: val.set_static_string("TODO"); break; + } + break; + } + break; + + case RowType.HEADER: + switch (column) { + case Columns.NAME: val.set_static_string("HEADER"); break; + case Columns.VALUE: val.set_string(p.header.to_string("0x%08X")); break; + case Columns.TARGET: val.set_static_string(""); break; + } + break; + + case RowType.BITFIELD: + /* TODO */ + break; + + case RowType.HEADER_BITFIELD: + switch (column) { + case Columns.NAME: val.set_static_string(packet_headers[p.type_id][bitfield_index(iter)]); break; + case Columns.TARGET: val.set_static_string(""); break; + case Columns.VALUE: + switch (p.type_id) { + case 0: + Packet0 p0 = p as Packet0; + switch (bitfield_index(iter)) { + case 0: val.set_string(translate_addr(p0._ADDR)); break; + case 1: val.set_string(p0._ONE_REG_WR.to_string()); break; + case 2: val.set_string(p0._COUNT.to_string()); break; + case 3: val.set_string(p.type_id.to_string()); break; + } + break; + case 1: + Packet1 p1 = p as Packet1; + switch (bitfield_index(iter)) { + case 0: val.set_string(translate_addr(p1._ADDR1)); break; + case 1: val.set_string(translate_addr(p1._ADDR2)); break; + case 2: val.set_string(p.type_id.to_string()); break; + } + break; + case 2: + switch (bitfield_index(iter)) { + case 0: val.set_string(p.type_id.to_string()); break; + } + break; + case 3: + Packet3 p3 = p as Packet3; + switch (bitfield_index(iter)) { + case 0: val.set_string(p3._IT_OPCODE.to_string("0x%02X")); break; /* TODO: resolve opcode */ + case 1: val.set_string(p3._COUNT.to_string()); break; + case 2: val.set_string(p.type_id.to_string()); break; + } + break; + } + break; + } + break; + } + } + + public bool iter_next(ref TreeIter iter) + { + var p = get_packet_num(iter); + switch (get_row_type(iter)) { + case RowType.PACKET: + p++; + if (p >= m_cs.packets.length) { return false; } + set_packet_num(ref iter, p); + break; + + case RowType.HEADER: + case RowType.DWORD: + var d = get_dword_num(iter)+1; + if (d > m_cs.packets[p].length+1) { return false; } + set_dword_num(ref iter, d); + break; + + case RowType.BITFIELD: + /* TODO */ + return false; + + case RowType.HEADER_BITFIELD: + var b = get_bitfield_num(iter)+1; + if (b > packet_headers_length[m_cs.packets[p].type_id]) { return false; } + set_bitfield_num(ref iter, b); + break; + } + + return true; + } + + public bool iter_children(out TreeIter iter, TreeIter? parent) + { + if (parent == null) { + if (m_cs.packets.length == 0) { + return false; + } + + set_iter(ref iter, 0, 0, 0); + return true; + } + + switch (get_row_type(parent)) { + case RowType.PACKET: set_iter(ref iter, get_packet_num(parent), 1, 0); return true; + case RowType.HEADER: set_iter(ref iter, get_packet_num(parent), 1, 1); return true; + case RowType.DWORD: + /* TODO */ + return false; + + case RowType.BITFIELD: return false; + case RowType.HEADER_BITFIELD: return false; + } + + return false; + } + + public bool iter_has_child(TreeIter iter) + { + switch (get_row_type(iter)) { + case RowType.PACKET: return true; + case RowType.HEADER: return true; + case RowType.DWORD: return false; /* TODO */ + case RowType.BITFIELD: return false; + case RowType.HEADER_BITFIELD: return false; + } + + return false; + } + + public int iter_n_children(TreeIter? iter) + { + if (iter == null) { + return m_cs.packets.length; + } + + var p = get_packet_num(iter); + switch (get_row_type(iter)) { + case RowType.PACKET: return (int)m_cs.packets[p].length+1; + case RowType.HEADER: return (int)packet_headers_length[m_cs.packets[p].type_id]; + case RowType.DWORD: return 0; /* TODO */ + case RowType.BITFIELD: return 0; + case RowType.HEADER_BITFIELD: return 0; + } + + return 0; + } + + public bool iter_nth_child(out TreeIter iter, TreeIter? parent, int n) + { + if (parent == null) { + if (n >= m_cs.packets.length || n < 0) { + return false; + } + + set_iter(ref iter, n, 0, 0); + return true; + } + + var p = get_packet_num(parent); + switch (get_row_type(parent)) { + case RowType.PACKET: + if (n > m_cs.packets[p].length || n < 0) { return false; } + set_iter(ref iter, p, n+1, 0); + return true; + + case RowType.HEADER: + if (n >= packet_headers_length[m_cs.packets[p].type_id] || n < 0) { return false; } + set_iter(ref iter, p, 1, n+1); + return true; + + case RowType.DWORD: return false; /* TODO */ + case RowType.BITFIELD: return false; + case RowType.HEADER_BITFIELD: return false; + } + + return false; + } + + public bool iter_parent(out TreeIter iter, TreeIter child) + { + if (has_bitfields(child)) { + set_iter(ref iter, get_packet_num(child), get_dword_num(child), 0); + return true; + } else if (has_dwords(child)) { + set_iter(ref iter, get_packet_num(child), 0, 0); + return true; + } + + return false; + } + + public void ref_node(TreeIter iter) { return; } + public void unref_node(TreeIter iter) { return; } + } + + public class CSView : Window + { +// private CS m_cs; + private Button m_pkgup; + private Button m_pkgdown; + private CSListModel m_pkg_store; + private ListStore m_reg_store; + private ListStore m_raw_store; + private uint m_pos; + + public CSView(CS cs, Spec spec) + { +// m_cs = cs; + m_pos = 0; + + var cs_list = new TreeView(); + cs_list.insert_column_with_data_func(-1, "", new Gtk.CellRendererPixbuf(), current_dword_renderer); + var ec_name = new Gtk.TreeViewColumn.with_attributes("Name", new Gtk.CellRendererText(), "text", CSListModel.Columns.NAME, null); + var ec_value = new Gtk.TreeViewColumn.with_attributes("Value", new Gtk.CellRendererText(), "text", CSListModel.Columns.VALUE, null); + var ec_target = new Gtk.TreeViewColumn.with_attributes("Target", new Gtk.CellRendererText(), "text", CSListModel.Columns.TARGET, null); + cs_list.insert_column(ec_name, -1); + cs_list.insert_column(ec_value, -1); + cs_list.insert_column(ec_target, -1); + ec_name.resizable = true; + ec_value.resizable = true; + ec_target.resizable = true; + cs_list.set_model(m_pkg_store = new CSListModel(cs, spec)); + cs_list.set_expander_column(ec_name); + + var cs_sw = new ScrolledWindow(null, null); + cs_sw.add(cs_list); + cs_sw.shadow_type = ShadowType.ETCHED_IN; + cs_sw.hscrollbar_policy = PolicyType.AUTOMATIC; + cs_sw.vscrollbar_policy = PolicyType.AUTOMATIC; + + var vbl = new VBox(false, 4); + vbl.pack_start(m_pkgup = new Button.from_stock("gtk-go-up"), false, true, 0); + vbl.pack_start(cs_sw, true, true, 0); + vbl.pack_start(m_pkgdown = new Button.from_stock("gtk-go-down"), false, true, 0); + + var state_reg_list = new TreeView(); + state_reg_list.set_model(m_reg_store = new ListStore(2, typeof(string), typeof(uint32))); + + var sreg_sw = new ScrolledWindow(null, null); + sreg_sw.add(state_reg_list); + sreg_sw.shadow_type = ShadowType.ETCHED_IN; + sreg_sw.hscrollbar_policy = PolicyType.AUTOMATIC; + sreg_sw.vscrollbar_policy = PolicyType.AUTOMATIC; + + var state_raw_list = new TreeView(); + state_raw_list.set_model(m_raw_store = new ListStore(2, typeof(string), typeof(uint32))); + + var sraw_sw = new ScrolledWindow(null, null); + sraw_sw.add(state_raw_list); + sraw_sw.shadow_type = ShadowType.ETCHED_IN; + sraw_sw.hscrollbar_policy = PolicyType.AUTOMATIC; + sraw_sw.vscrollbar_policy = PolicyType.AUTOMATIC; + + var nb = new Notebook(); + nb.append_page(sreg_sw, new Label("Registers")); + nb.append_page(sraw_sw, new Label("Raw")); + nb.scrollable = true; + + var paned = new HPaned(); + paned.add1(vbl); + paned.add2(nb); + paned.position = 400; + + this.add(paned); + this.border_width = 10; + this.set_default_size(640, 480); + } + + private void current_dword_renderer(Gtk.TreeViewColumn tree_column, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) + { + if (m_pos == (model as CSListModel).get_packet_num(iter)) { + (cell as Gtk.CellRendererPixbuf).stock_id = "gtk-media-record"; + } else { + (cell as Gtk.CellRendererPixbuf).stock_id = ""; + } + } + } +} + |