summaryrefslogtreecommitdiff
path: root/src/csview.vala
diff options
context:
space:
mode:
Diffstat (limited to 'src/csview.vala')
-rw-r--r--src/csview.vala540
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 = "";
+ }
+ }
+ }
+}
+