summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--utils/regtools/desc/XML.txt5
-rw-r--r--utils/regtools/desc/regs-1.0.dtd28
-rw-r--r--utils/regtools/headergen.cpp6
-rw-r--r--utils/regtools/lib/soc_desc.cpp700
-rw-r--r--utils/regtools/lib/soc_desc.hpp49
-rw-r--r--utils/regtools/qeditor/analyser.h5
-rw-r--r--utils/regtools/qeditor/aux.cpp746
-rw-r--r--utils/regtools/qeditor/aux.h227
-rw-r--r--utils/regtools/qeditor/backend.cpp67
-rw-r--r--utils/regtools/qeditor/backend.h79
-rw-r--r--utils/regtools/qeditor/mainwindow.cpp63
-rw-r--r--utils/regtools/qeditor/mainwindow.h16
-rw-r--r--utils/regtools/qeditor/qeditor.pro6
-rw-r--r--utils/regtools/qeditor/regdisplaypanel.cpp314
-rw-r--r--utils/regtools/qeditor/regdisplaypanel.h77
-rw-r--r--utils/regtools/qeditor/regedit.cpp1324
-rw-r--r--utils/regtools/qeditor/regedit.h282
-rw-r--r--utils/regtools/qeditor/regtab.cpp534
-rw-r--r--utils/regtools/qeditor/regtab.h119
-rw-r--r--utils/regtools/qeditor/std_analysers.cpp9
-rw-r--r--utils/regtools/qeditor/std_analysers.h4
-rw-r--r--utils/regtools/tester.cpp344
22 files changed, 4390 insertions, 614 deletions
diff --git a/utils/regtools/desc/XML.txt b/utils/regtools/desc/XML.txt
index a90f875f66..3c28154a1f 100644
--- a/utils/regtools/desc/XML.txt
+++ b/utils/regtools/desc/XML.txt
@@ -9,6 +9,11 @@ Example:
9<!-- desc --> 9<!-- desc -->
10</xml> 10</xml>
11 11
12Root Element: root
13------------------
14The root element can either be "soc" tag if the file contains a single description,
15or "root" with no properties and one or more "soc" tags as children.
16
12Element: soc 17Element: soc
13------------ 18------------
14The XML can contain one or more SoC description. Each description is enclosed in 19The XML can contain one or more SoC description. Each description is enclosed in
diff --git a/utils/regtools/desc/regs-1.0.dtd b/utils/regtools/desc/regs-1.0.dtd
new file mode 100644
index 0000000000..3204d29195
--- /dev/null
+++ b/utils/regtools/desc/regs-1.0.dtd
@@ -0,0 +1,28 @@
1<!-- Format specification of the 1.0 register description files. Files are
2 considered to be version 1.0 if no version field is specified -->
3<!ELEMENT soc (dev)*>
4<!ATTLIST soc name CDATA #REQUIRED>
5<!ATTLIST soc desc CDATA #IMPLIED>
6<!ELEMENT dev (addr|reg)*>
7<!ATTLIST dev name CDATA #REQUIRED>
8<!ATTLIST dev long_name CDATA #IMPLIED>
9<!ATTLIST dev desc CDATA #IMPLIED>
10<!ATTLIST dev version CDATA #IMPLIED>
11<!ELEMENT addr EMPTY>
12<!ATTLIST addr name CDATA #REQUIRED>
13<!ATTLIST addr addr CDATA #REQUIRED>
14<!ELEMENT reg (addr|field|formula)*>
15<!ATTLIST reg name CDATA #REQUIRED>
16<!ATTLIST reg addr CDATA #IMPLIED>
17<!ATTLIST reg desc CDATA #IMPLIED>
18<!ATTLIST reg sct (yes|no) "no">
19<!ELEMENT formula EMPTY>
20<!ATTLIST formula string CDATA #IMPLIED>
21<!ELEMENT field (value)*>
22<!ATTLIST field name CDATA #REQUIRED>
23<!ATTLIST field desc CDATA #IMPLIED>
24<!ATTLIST field bitrange CDATA #REQUIRED>
25<!ELEMENT value EMPTY>
26<!ATTLIST value name CDATA #REQUIRED>
27<!ATTLIST value value CDATA #REQUIRED>
28<!ATTLIST value desc CDATA #IMPLIED>
diff --git a/utils/regtools/headergen.cpp b/utils/regtools/headergen.cpp
index a95dc46215..b4ade5f186 100644
--- a/utils/regtools/headergen.cpp
+++ b/utils/regtools/headergen.cpp
@@ -574,11 +574,15 @@ int main(int argc, char **argv)
574 574
575 std::vector< soc_t > socs; 575 std::vector< soc_t > socs;
576 for(int i = optind; i < argc - 1; i++) 576 for(int i = optind; i < argc - 1; i++)
577 if(!soc_desc_parse_xml(argv[i], socs)) 577 {
578 soc_t s;
579 if(!soc_desc_parse_xml(argv[i], s))
578 { 580 {
579 printf("Cannot parse %s\n", argv[i]); 581 printf("Cannot parse %s\n", argv[i]);
580 return 1; 582 return 1;
581 } 583 }
584 socs.push_back(s);
585 }
582 586
583 g_gen_selector = force_selector || socs.size() > 1; 587 g_gen_selector = force_selector || socs.size() > 1;
584 588
diff --git a/utils/regtools/lib/soc_desc.cpp b/utils/regtools/lib/soc_desc.cpp
index 6a6d47648f..1c9eaf7972 100644
--- a/utils/regtools/lib/soc_desc.cpp
+++ b/utils/regtools/lib/soc_desc.cpp
@@ -21,8 +21,12 @@
21#include "soc_desc.hpp" 21#include "soc_desc.hpp"
22#include <libxml/parser.h> 22#include <libxml/parser.h>
23#include <libxml/tree.h> 23#include <libxml/tree.h>
24#include <libxml/xmlsave.h>
25#include <libxml/xmlwriter.h>
24#include <stdio.h> 26#include <stdio.h>
25#include <string.h> 27#include <string.h>
28#include <algorithm>
29#include <cctype>
26 30
27#define XML_CHAR_TO_CHAR(s) ((const char *)(s)) 31#define XML_CHAR_TO_CHAR(s) ((const char *)(s))
28 32
@@ -78,6 +82,9 @@
78#define END_NODE_MATCH() \ 82#define END_NODE_MATCH() \
79 } 83 }
80 84
85namespace
86{
87
81bool validate_string_hook(const std::string& str, std::string& s) 88bool validate_string_hook(const std::string& str, std::string& s)
82{ 89{
83 s = str; 90 s = str;
@@ -137,6 +144,7 @@ bool parse_value_elem(xmlNode *node, soc_reg_field_value_t& value)
137 BEGIN_ATTR_MATCH(node->properties) 144 BEGIN_ATTR_MATCH(node->properties)
138 MATCH_TEXT_ATTR("name", value.name) 145 MATCH_TEXT_ATTR("name", value.name)
139 MATCH_UINT32_ATTR("value", value.value) 146 MATCH_UINT32_ATTR("value", value.value)
147 MATCH_TEXT_ATTR("desc", value.desc)
140 END_ATTR_MATCH() 148 END_ATTR_MATCH()
141 149
142 return true; 150 return true;
@@ -256,28 +264,706 @@ bool parse_soc_elem(xmlNode *node, soc_t& soc)
256 return true; 264 return true;
257} 265}
258 266
259bool parse_root_elem(xmlNode *node, std::vector< soc_t >& soc) 267bool parse_root_elem(xmlNode *node, soc_t& soc)
260{ 268{
269 std::vector< soc_t > socs;
261 BEGIN_NODE_MATCH(node) 270 BEGIN_NODE_MATCH(node)
262 MATCH_ELEM_NODE("soc", soc, parse_soc_elem) 271 MATCH_ELEM_NODE("soc", socs, parse_soc_elem)
263 END_NODE_MATCH() 272 END_NODE_MATCH()
273 if(socs.size() != 1)
274 {
275 fprintf(stderr, "A description file must contain exactly one soc element\n");
276 return false;
277 }
278 soc = socs[0];
264 return true; 279 return true;
265} 280}
266 281
267bool soc_desc_parse_xml(const std::string& filename, std::vector< soc_t >& socs) 282}
283
284bool soc_desc_parse_xml(const std::string& filename, soc_t& socs)
268{ 285{
269 LIBXML_TEST_VERSION 286 LIBXML_TEST_VERSION
270 287
271 xmlDoc *doc = xmlReadFile(filename.c_str(), NULL, 0); 288 xmlDocPtr doc = xmlReadFile(filename.c_str(), NULL, 0);
272 if(doc == NULL) 289 if(doc == NULL)
273 return false; 290 return false;
274 291
275 xmlNode *root_element = xmlDocGetRootElement(doc); 292 xmlNodePtr root_element = xmlDocGetRootElement(doc);
276
277 bool ret = parse_root_elem(root_element, socs); 293 bool ret = parse_root_elem(root_element, socs);
278 294
279 xmlFreeDoc(doc); 295 xmlFreeDoc(doc);
280 xmlCleanupParser(); 296 xmlCleanupParser();
281 297
282 return ret; 298 return ret;
283} \ No newline at end of file 299}
300
301namespace
302{
303
304int produce_field(xmlTextWriterPtr writer, const soc_reg_field_t& field)
305{
306#define SAFE(x) if((x) < 0) return -1;
307 /* <field> */
308 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "field"));
309 /* name */
310 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.name.c_str()));
311 /* desc */
312 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.desc.c_str()));
313 /* bitrange */
314 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "bitrange", "%d:%d",
315 field.last_bit, field.first_bit));
316 /* values */
317 for(size_t i = 0; i < field.value.size(); i++)
318 {
319 /* <value> */
320 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "value"));
321 /* name */
322 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST field.value[i].name.c_str()));
323 /* value */
324 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "value", "0x%x", field.value[i].value));
325 /* name */
326 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST field.value[i].desc.c_str()));
327 /* </value> */
328 SAFE(xmlTextWriterEndElement(writer));
329 }
330 /* </field> */
331 SAFE(xmlTextWriterEndElement(writer));
332#undef SAFE
333 return 0;
334}
335
336int produce_reg(xmlTextWriterPtr writer, const soc_reg_t& reg)
337{
338#define SAFE(x) if((x) < 0) return -1;
339 /* <reg> */
340 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "reg"));
341 /* name */
342 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.name.c_str()));
343 /* name */
344 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST reg.desc.c_str()));
345 /* flags */
346 if(reg.flags & REG_HAS_SCT)
347 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "sct", BAD_CAST "yes"));
348 /* formula */
349 if(reg.formula.type != REG_FORMULA_NONE)
350 {
351 /* <formula> */
352 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "formula"));
353 switch(reg.formula.type)
354 {
355 case REG_FORMULA_STRING:
356 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "string",
357 BAD_CAST reg.formula.string.c_str()));
358 break;
359 default:
360 break;
361 }
362 /* </formula> */
363 SAFE(xmlTextWriterEndElement(writer));
364 }
365 /* addresses */
366 for(size_t i = 0; i < reg.addr.size(); i++)
367 {
368 /* <addr> */
369 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr"));
370 /* name */
371 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST reg.addr[i].name.c_str()));
372 /* addr */
373 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", reg.addr[i].addr));
374 /* </addr> */
375 SAFE(xmlTextWriterEndElement(writer));
376 }
377 /* fields */
378 for(size_t i = 0; i < reg.field.size(); i++)
379 produce_field(writer, reg.field[i]);
380 /* </reg> */
381 SAFE(xmlTextWriterEndElement(writer));
382#undef SAFE
383 return 0;
384}
385
386int produce_dev(xmlTextWriterPtr writer, const soc_dev_t& dev)
387{
388#define SAFE(x) if((x) < 0) return -1;
389 /* <dev> */
390 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "dev"));
391 /* name */
392 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.name.c_str()));
393 /* long_name */
394 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "long_name", BAD_CAST dev.long_name.c_str()));
395 /* desc */
396 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST dev.desc.c_str()));
397 /* version */
398 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "version", BAD_CAST dev.version.c_str()));
399 /* addresses */
400 for(size_t i = 0; i < dev.addr.size(); i++)
401 {
402 /* <addr> */
403 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "addr"));
404 /* name */
405 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST dev.addr[i].name.c_str()));
406 /* addr */
407 SAFE(xmlTextWriterWriteFormatAttribute(writer, BAD_CAST "addr", "0x%x", dev.addr[i].addr));
408 /* </addr> */
409 SAFE(xmlTextWriterEndElement(writer));
410 }
411 /* registers */
412 for(size_t i = 0; i < dev.reg.size(); i++)
413 produce_reg(writer, dev.reg[i]);
414 /* </dev> */
415 SAFE(xmlTextWriterEndElement(writer));
416#undef SAFE
417 return 0;
418}
419
420}
421
422bool soc_desc_produce_xml(const std::string& filename, const soc_t& soc)
423{
424 LIBXML_TEST_VERSION
425
426 xmlTextWriterPtr writer = xmlNewTextWriterFilename(filename.c_str(), 0);
427 if(writer == NULL)
428 return false;
429#define SAFE(x) if((x) < 0) goto Lerr
430 SAFE(xmlTextWriterSetIndent(writer, 1));
431 SAFE(xmlTextWriterSetIndentString(writer, BAD_CAST " "));
432 /* <xml> */
433 SAFE(xmlTextWriterStartDocument(writer, NULL, NULL, NULL));
434 /* <soc> */
435 SAFE(xmlTextWriterStartElement(writer, BAD_CAST "soc"));
436 /* name */
437 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "name", BAD_CAST soc.name.c_str()));
438 /* desc */
439 SAFE(xmlTextWriterWriteAttribute(writer, BAD_CAST "desc", BAD_CAST soc.desc.c_str()));
440 /* devices */
441 for(size_t i = 0; i < soc.dev.size(); i++)
442 SAFE(produce_dev(writer, soc.dev[i]));
443 /* end <soc> */
444 SAFE(xmlTextWriterEndElement(writer));
445 /* </xml> */
446 SAFE(xmlTextWriterEndDocument(writer));
447 xmlFreeTextWriter(writer);
448 return true;
449#undef SAFE
450Lerr:
451 xmlFreeTextWriter(writer);
452 return false;
453}
454
455namespace
456{
457
458struct soc_sorter
459{
460 bool operator()(const soc_dev_t& a, const soc_dev_t& b) const
461 {
462 return a.name < b.name;
463 }
464
465 bool operator()(const soc_dev_addr_t& a, const soc_dev_addr_t& b) const
466 {
467 return a.name < b.name;
468 }
469
470 bool operator()(const soc_reg_t& a, const soc_reg_t& b) const
471 {
472 soc_addr_t aa = a.addr.size() > 0 ? a.addr[0].addr : 0;
473 soc_addr_t ab = b.addr.size() > 0 ? b.addr[0].addr : 0;
474 return aa < ab;
475 }
476
477 bool operator()(const soc_reg_addr_t& a, const soc_reg_addr_t& b) const
478 {
479 return a.addr < b.addr;
480 }
481
482 bool operator()(const soc_reg_field_t& a, const soc_reg_field_t& b) const
483 {
484 return a.last_bit > b.last_bit;
485 }
486
487 bool operator()(const soc_reg_field_value_t a, const soc_reg_field_value_t& b) const
488 {
489 return a.value < b.value;
490 }
491};
492
493void normalize(soc_reg_field_t& field)
494{
495 std::sort(field.value.begin(), field.value.end(), soc_sorter());
496}
497
498void normalize(soc_reg_t& reg)
499{
500 std::sort(reg.addr.begin(), reg.addr.end(), soc_sorter());
501 std::sort(reg.field.begin(), reg.field.end(), soc_sorter());
502 for(size_t i = 0; i < reg.field.size(); i++)
503 normalize(reg.field[i]);
504}
505
506void normalize(soc_dev_t& dev)
507{
508 std::sort(dev.addr.begin(), dev.addr.end(), soc_sorter());
509 std::sort(dev.reg.begin(), dev.reg.end(), soc_sorter());
510 for(size_t i = 0; i < dev.reg.size(); i++)
511 normalize(dev.reg[i]);
512}
513
514}
515
516void soc_desc_normalize(soc_t& soc)
517{
518 std::sort(soc.dev.begin(), soc.dev.end(), soc_sorter());
519 for(size_t i = 0; i < soc.dev.size(); i++)
520 normalize(soc.dev[i]);
521}
522
523namespace
524{
525 soc_error_t make_error(soc_error_level_t lvl, std::string at, std::string what)
526 {
527 soc_error_t err;
528 err.level = lvl;
529 err.location = at;
530 err.message = what;
531 return err;
532 }
533
534 soc_error_t make_warning(std::string at, std::string what)
535 {
536 return make_error(SOC_ERROR_WARNING, at, what);
537 }
538
539 soc_error_t make_fatal(std::string at, std::string what)
540 {
541 return make_error(SOC_ERROR_FATAL, at, what);
542 }
543
544 soc_error_t prefix(soc_error_t err, const std::string& prefix_at)
545 {
546 err.location = prefix_at + "." + err.location;
547 return err;
548 }
549
550 void add_errors(std::vector< soc_error_t >& errors,
551 const std::vector< soc_error_t >& new_errors, const std::string& prefix_at)
552 {
553 for(size_t i = 0; i < new_errors.size(); i++)
554 errors.push_back(prefix(new_errors[i], prefix_at));
555 }
556
557 std::vector< soc_error_t > no_error()
558 {
559 std::vector< soc_error_t > s;
560 return s;
561 }
562
563 std::vector< soc_error_t > one_error(const soc_error_t& err)
564 {
565 std::vector< soc_error_t > s;
566 s.push_back(err);
567 return s;
568 }
569
570 bool name_valid(char c)
571 {
572 return (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
573 (c >= 'A' && c <= 'Z') || c == '_';
574 }
575
576 bool name_valid(const std::string& s)
577 {
578 for(size_t i = 0; i < s.size(); i++)
579 if(!name_valid(s[i]))
580 return false;
581 return true;
582 }
583}
584
585std::vector< soc_error_t > soc_reg_field_value_t::errors(bool recursive)
586{
587 (void) recursive;
588 if(name.size() == 0)
589 return one_error(make_fatal(name, "empty name"));
590 else if(!name_valid(name))
591 return one_error(make_fatal(name, "invalid name"));
592 else
593 return no_error();
594}
595
596std::vector< soc_error_t > soc_reg_field_t::errors(bool recursive)
597{
598 std::vector< soc_error_t > err;
599 std::string at(name);
600 if(name.size() == 0)
601 err.push_back(make_fatal(at, "empty name"));
602 else if(!name_valid(name))
603 err.push_back(make_fatal(at, "invalid name"));
604 if(last_bit > 31)
605 err.push_back(make_fatal(at, "last bit is greater than 31"));
606 if(first_bit > last_bit)
607 err.push_back(make_fatal(at, "last bit is greater than first bit"));
608 for(size_t i = 0; i < value.size(); i++)
609 {
610 for(size_t j = 0; j < value.size(); j++)
611 {
612 if(i == j)
613 continue;
614 if(value[i].name == value[j].name)
615 err.push_back(prefix(make_fatal(value[i].name,
616 "there are several values with the same name"), at));
617 if(value[i].value == value[j].value)
618 err.push_back(prefix(make_warning(value[i].name,
619 "there are several values with the same value"), at));
620 }
621 if(value[i].value > (bitmask() >> first_bit))
622 err.push_back(prefix(make_warning(at, "value doesn't fit into the field"), value[i].name));
623 if(recursive)
624 add_errors(err, value[i].errors(true), at);
625 }
626 return err;
627}
628
629std::vector< soc_error_t > soc_reg_addr_t::errors(bool recursive)
630{
631 (void) recursive;
632 if(name.size() == 0)
633 return one_error(make_fatal("", "empty name"));
634 else if(!name_valid(name))
635 return one_error(make_fatal(name, "invalid name"));
636 else
637 return no_error();
638}
639
640std::vector< soc_error_t > soc_reg_formula_t::errors(bool recursive)
641{
642 (void) recursive;
643 if(type == REG_FORMULA_STRING && string.size() == 0)
644 return one_error(make_fatal("", "empty string formula"));
645 else
646 return no_error();
647}
648
649namespace
650{
651
652bool field_overlap(const soc_reg_field_t& a, const soc_reg_field_t& b)
653{
654 return !(a.first_bit > b.last_bit || b.first_bit > a.last_bit);
655}
656
657}
658
659std::vector< soc_error_t > soc_reg_t::errors(bool recursive)
660{
661 std::vector< soc_error_t > err;
662 std::string at(name);
663 if(name.size() == 0)
664 err.push_back(make_fatal(at, "empty name"));
665 else if(!name_valid(name))
666 err.push_back(make_fatal(at, "invalid name"));
667 for(size_t i = 0; i < addr.size(); i++)
668 {
669 for(size_t j = 0; j < addr.size(); j++)
670 {
671 if(i == j)
672 continue;
673 if(addr[i].name == addr[j].name)
674 err.push_back(prefix(make_fatal(addr[i].name,
675 "there are several instances with the same name"), at));
676 if(addr[i].addr == addr[j].addr)
677 err.push_back(prefix(make_fatal(addr[i].name,
678 "there are several instances with the same address"), at));
679 }
680 if(recursive)
681 add_errors(err, addr[i].errors(true), at);
682 }
683 if(recursive)
684 add_errors(err, formula.errors(true), at);
685 for(size_t i = 0; i < field.size(); i++)
686 {
687 for(size_t j = 0; j < field.size(); j++)
688 {
689 if(i == j)
690 continue;
691 if(field[i].name == field[j].name)
692 err.push_back(prefix(make_fatal(field[i].name,
693 "there are several fields with the same name"), at));
694 if(field_overlap(field[i], field[j]))
695 err.push_back(prefix(make_fatal(field[i].name,
696 "there are overlapping fields"), at));
697 }
698 if(recursive)
699 add_errors(err, field[i].errors(true), at);
700 }
701 return err;
702}
703
704std::vector< soc_error_t > soc_dev_addr_t::errors(bool recursive)
705{
706 (void) recursive;
707 if(name.size() == 0)
708 return one_error(make_fatal("", "empty name"));
709 else if(!name_valid(name))
710 return one_error(make_fatal(name, "invalid name"));
711 else
712 return no_error();
713}
714
715std::vector< soc_error_t > soc_dev_t::errors(bool recursive)
716{
717 std::vector< soc_error_t > err;
718 std::string at(name);
719 if(name.size() == 0)
720 err.push_back(make_fatal(at, "empty name"));
721 else if(!name_valid(name))
722 err.push_back(make_fatal(at, "invalid name"));
723 for(size_t i = 0; i < addr.size(); i++)
724 {
725 for(size_t j = 0; j < addr.size(); j++)
726 {
727 if(i == j)
728 continue;
729 if(addr[i].name == addr[j].name)
730 err.push_back(prefix(make_fatal(addr[i].name,
731 "there are several instances with the same name"), at));
732 if(addr[i].addr == addr[j].addr)
733 err.push_back(prefix(make_fatal(addr[i].name,
734 "there are several instances with the same address"), at));
735 }
736 if(recursive)
737 add_errors(err, addr[i].errors(true), at);
738 }
739 for(size_t i = 0; i < reg.size(); i++)
740 {
741 for(size_t j = 0; j < reg.size(); j++)
742 {
743 if(i == j)
744 continue;
745 if(reg[i].name == reg[j].name)
746 err.push_back(prefix(make_fatal(reg[i].name,
747 "there are several registers with the same name"), at));
748 }
749 if(recursive)
750 add_errors(err, reg[i].errors(true), at);
751 }
752 return err;
753}
754
755std::vector< soc_error_t > soc_t::errors(bool recursive)
756{
757 std::vector< soc_error_t > err;
758 std::string at(name);
759 for(size_t i = 0; i < dev.size(); i++)
760 {
761 for(size_t j = 0; j < dev.size(); j++)
762 {
763 if(i == j)
764 continue;
765 if(dev[i].name == dev[j].name)
766 err.push_back(prefix(make_fatal(dev[i].name,
767 "there are several devices with the same name"), at));
768 }
769 if(recursive)
770 add_errors(err, dev[i].errors(true), at);
771 }
772 return err;
773}
774
775namespace
776{
777
778struct formula_evaluator
779{
780 std::string formula;
781 size_t pos;
782 std::string error;
783
784 bool err(const char *fmt, ...)
785 {
786 char buffer[256];
787 va_list args;
788 va_start(args, fmt);
789 vsnprintf(buffer,sizeof(buffer), fmt, args);
790 va_end(args);
791 error = buffer;
792 return false;
793 }
794
795 formula_evaluator(const std::string& s):pos(0)
796 {
797 for(size_t i = 0; i < s.size(); i++)
798 if(!isspace(s[i]))
799 formula.push_back(s[i]);
800 }
801
802 void adv()
803 {
804 pos++;
805 }
806
807 char cur()
808 {
809 return end() ? 0 : formula[pos];
810 }
811
812 bool end()
813 {
814 return pos >= formula.size();
815 }
816
817 bool parse_digit(char c, int basis, soc_word_t& res)
818 {
819 c = tolower(c);
820 if(isdigit(c))
821 {
822 res = c - '0';
823 return true;
824 }
825 if(basis == 16 && isxdigit(c))
826 {
827 res = c + 10 - 'a';
828 return true;
829 }
830 return err("invalid digit '%c'", c);
831 }
832
833 bool parse_signed(soc_word_t& res)
834 {
835 char op = cur();
836 if(op == '+' || op == '-')
837 {
838 adv();
839 if(!parse_signed(res))
840 return false;
841 if(op == '-')
842 res *= -1;
843 return true;
844 }
845 else if(op == '(')
846 {
847 adv();
848 if(!parse_expression(res))
849 return false;
850 if(cur() != ')')
851 return err("expected ')', got '%c'", cur());
852 adv();
853 return true;
854 }
855 else if(isdigit(op))
856 {
857 res = op - '0';
858 adv();
859 int basis = 10;
860 if(op == '0' && cur() == 'x')
861 {
862 basis = 16;
863 adv();
864 }
865 soc_word_t digit = 0;
866 while(parse_digit(cur(), basis, digit))
867 {
868 res = res * basis + digit;
869 adv();
870 }
871 return true;
872 }
873 else if(isalpha(op) || op == '_')
874 {
875 std::string name;
876 while(isalnum(cur()) || cur() == '_')
877 {
878 name.push_back(cur());
879 adv();
880 }
881 return get_variable(name, res);
882 }
883 else
884 return err("express signed expression, got '%c'", op);
885 }
886
887 bool parse_term(soc_word_t& res)
888 {
889 if(!parse_signed(res))
890 return false;
891 while(cur() == '*' || cur() == '/' || cur() == '%')
892 {
893 char op = cur();
894 adv();
895 soc_word_t tmp;
896 if(!parse_signed(tmp))
897 return false;
898 if(op == '*')
899 res *= tmp;
900 else if(tmp != 0)
901 res = op == '/' ? res / tmp : res % tmp;
902 else
903 return err("division by 0");
904 }
905 return true;
906 }
907
908 bool parse_expression(soc_word_t& res)
909 {
910 if(!parse_term(res))
911 return false;
912 while(!end() && (cur() == '+' || cur() == '-'))
913 {
914 char op = cur();
915 adv();
916 soc_word_t tmp;
917 if(!parse_term(tmp))
918 return false;
919 if(op == '+')
920 res += tmp;
921 else
922 res -= tmp;
923 }
924 return true;
925 }
926
927 bool parse(soc_word_t& res, std::string& _error)
928 {
929 bool ok = parse_expression(res);
930 if(ok && !end())
931 err("unexpected character '%c'", cur());
932 _error = error;
933 return ok && end();
934 }
935
936 virtual bool get_variable(std::string name, soc_word_t& res)
937 {
938 return err("unknown variable '%s'", name.c_str());
939 }
940};
941
942struct my_evaluator : public formula_evaluator
943{
944 const std::map< std::string, soc_word_t>& var;
945
946 my_evaluator(const std::string& formula, const std::map< std::string, soc_word_t>& _var)
947 :formula_evaluator(formula), var(_var) {}
948
949 virtual bool get_variable(std::string name, soc_word_t& res)
950 {
951 std::map< std::string, soc_word_t>::const_iterator it = var.find(name);
952 if(it == var.end())
953 return formula_evaluator::get_variable(name, res);
954 else
955 {
956 res = it->second;
957 return true;
958 }
959 }
960};
961
962}
963
964bool soc_desc_evaluate_formula(const std::string& formula,
965 const std::map< std::string, soc_word_t>& var, soc_word_t& result, std::string& error)
966{
967 my_evaluator e(formula, var);
968 return e.parse(result, error);
969}
diff --git a/utils/regtools/lib/soc_desc.hpp b/utils/regtools/lib/soc_desc.hpp
index efaf813eb2..d9dbf0cc20 100644
--- a/utils/regtools/lib/soc_desc.hpp
+++ b/utils/regtools/lib/soc_desc.hpp
@@ -25,6 +25,7 @@
25#include <vector> 25#include <vector>
26#include <list> 26#include <list>
27#include <string> 27#include <string>
28#include <map>
28 29
29/** 30/**
30 * These data structures represent the SoC register in a convenient way. 31 * These data structures represent the SoC register in a convenient way.
@@ -50,6 +51,21 @@ typedef uint32_t soc_addr_t;
50typedef uint32_t soc_word_t; 51typedef uint32_t soc_word_t;
51typedef uint32_t soc_reg_flags_t; 52typedef uint32_t soc_reg_flags_t;
52 53
54/** SoC error gravity level */
55enum soc_error_level_t
56{
57 SOC_ERROR_WARNING,
58 SOC_ERROR_FATAL,
59};
60
61/** SoC description error */
62struct soc_error_t
63{
64 soc_error_level_t level; /// level (warning, fatal, ...)
65 std::string location; /// human description of the location
66 std::string message; /// message
67};
68
53/** SoC register generic formula */ 69/** SoC register generic formula */
54enum soc_reg_formula_type_t 70enum soc_reg_formula_type_t
55{ 71{
@@ -66,6 +82,8 @@ struct soc_reg_field_value_t
66 std::string name; /// name of the value 82 std::string name; /// name of the value
67 soc_word_t value; /// numeric value 83 soc_word_t value; /// numeric value
68 std::string desc; /// human description 84 std::string desc; /// human description
85
86 std::vector< soc_error_t > errors(bool recursive);
69}; 87};
70 88
71/** SoC register field */ 89/** SoC register field */
@@ -90,6 +108,8 @@ struct soc_reg_field_t
90 } 108 }
91 109
92 std::vector< soc_reg_field_value_t > value; 110 std::vector< soc_reg_field_value_t > value;
111
112 std::vector< soc_error_t > errors(bool recursive);
93}; 113};
94 114
95/** SoC register address */ 115/** SoC register address */
@@ -97,6 +117,8 @@ struct soc_reg_addr_t
97{ 117{
98 std::string name; /// actual register name 118 std::string name; /// actual register name
99 soc_addr_t addr; /// actual register address (relative to device) 119 soc_addr_t addr; /// actual register address (relative to device)
120
121 std::vector< soc_error_t > errors(bool recursive);
100}; 122};
101 123
102/** SoC register formula */ 124/** SoC register formula */
@@ -104,6 +126,8 @@ struct soc_reg_formula_t
104{ 126{
105 enum soc_reg_formula_type_t type; 127 enum soc_reg_formula_type_t type;
106 std::string string; /// for STRING 128 std::string string; /// for STRING
129
130 std::vector< soc_error_t > errors(bool recursive);
107}; 131};
108 132
109/** SoC register */ 133/** SoC register */
@@ -116,6 +140,8 @@ struct soc_reg_t
116 soc_reg_flags_t flags; /// ORed value 140 soc_reg_flags_t flags; /// ORed value
117 141
118 std::vector< soc_reg_field_t > field; 142 std::vector< soc_reg_field_t > field;
143
144 std::vector< soc_error_t > errors(bool recursive);
119}; 145};
120 146
121/** Soc device address */ 147/** Soc device address */
@@ -123,6 +149,8 @@ struct soc_dev_addr_t
123{ 149{
124 std::string name; /// actual device name 150 std::string name; /// actual device name
125 soc_addr_t addr; 151 soc_addr_t addr;
152
153 std::vector< soc_error_t > errors(bool recursive);
126}; 154};
127 155
128/** SoC device */ 156/** SoC device */
@@ -135,6 +163,8 @@ struct soc_dev_t
135 std::vector< soc_dev_addr_t > addr; 163 std::vector< soc_dev_addr_t > addr;
136 164
137 std::vector< soc_reg_t > reg; 165 std::vector< soc_reg_t > reg;
166
167 std::vector< soc_error_t > errors(bool recursive);
138}; 168};
139 169
140/** SoC */ 170/** SoC */
@@ -144,10 +174,23 @@ struct soc_t
144 std::string desc; /// SoC name 174 std::string desc; /// SoC name
145 175
146 std::vector< soc_dev_t > dev; 176 std::vector< soc_dev_t > dev;
177
178 std::vector< soc_error_t > errors(bool recursive);
147}; 179};
148 180
149/** Parse a SoC description from a XML file, append it to <soc>. A file 181/** Parse a SoC description from a XML file, append it to <soc>. */
150 * can contain multiple SoC descriptions */ 182bool soc_desc_parse_xml(const std::string& filename, soc_t& soc);
151bool soc_desc_parse_xml(const std::string& filename, std::vector< soc_t >& soc); 183/** Write a SoC description to a XML file, overwriting it. A file can contain
184 * multiple Soc descriptions */
185bool soc_desc_produce_xml(const std::string& filename, const soc_t& soc);
186/** Normalise a soc description by reordering elemnts so that:
187 * - devices are sorted by first name
188 * - registers are sorted by first address
189 * - fields are sorted by last bit
190 * - values are sorted by value */
191void soc_desc_normalize(soc_t& soc);
192/** Formula parser: try to parse and evaluate a formula to a specific value of 'n' */
193bool soc_desc_evaluate_formula(const std::string& formula,
194 const std::map< std::string, soc_word_t>& var, soc_word_t& result, std::string& error);
152 195
153#endif /* __SOC_DESC__ */ \ No newline at end of file 196#endif /* __SOC_DESC__ */ \ No newline at end of file
diff --git a/utils/regtools/qeditor/analyser.h b/utils/regtools/qeditor/analyser.h
index a06652bfb0..4f9830ac4c 100644
--- a/utils/regtools/qeditor/analyser.h
+++ b/utils/regtools/qeditor/analyser.h
@@ -5,13 +5,14 @@
5#include <QVector> 5#include <QVector>
6#include <QString> 6#include <QString>
7#include "backend.h" 7#include "backend.h"
8#include "regtab.h"
8 9
9class Analyser : public QObject 10class Analyser : public RegTabPanel
10{ 11{
11 Q_OBJECT
12public: 12public:
13 Analyser(const SocRef& soc, IoBackend *backend); 13 Analyser(const SocRef& soc, IoBackend *backend);
14 virtual ~Analyser(); 14 virtual ~Analyser();
15 virtual void AllowWrite(bool en) { Q_UNUSED(en); }
15 virtual QWidget *GetWidget() = 0; 16 virtual QWidget *GetWidget() = 0;
16 17
17protected: 18protected:
diff --git a/utils/regtools/qeditor/aux.cpp b/utils/regtools/qeditor/aux.cpp
new file mode 100644
index 0000000000..0614bb57f6
--- /dev/null
+++ b/utils/regtools/qeditor/aux.cpp
@@ -0,0 +1,746 @@
1#include "aux.h"
2#include <QFontMetrics>
3#include <QPainter>
4#include <QTextDocument>
5#include <QAbstractTextDocumentLayout>
6#include <QHeaderView>
7#include <QDebug>
8#include <QElapsedTimer>
9#include <QXmlStreamReader>
10#include <QXmlStreamWriter>
11#include <QTextBlock>
12
13/**
14 * SocBitRangeValidator
15 */
16SocBitRangeValidator::SocBitRangeValidator(QObject *parent)
17 :QValidator(parent)
18{
19}
20
21void SocBitRangeValidator::fixup(QString& input) const
22{
23 input = input.trimmed();
24}
25
26QValidator::State SocBitRangeValidator::validate(QString& input, int& pos) const
27{
28 Q_UNUSED(pos);
29 int first, last;
30 State state = parse(input, last, first);
31 return state;
32}
33
34QValidator::State SocBitRangeValidator::parse(const QString& input, int& last, int& first) const
35{
36 // the empty string is always intermediate
37 if(input.size() == 0)
38 return Intermediate;
39 // check if there is ':'
40 int pos = input.indexOf(':');
41 if(pos == -1)
42 pos = input.size();
43 // if field start with ':', the last bit is implicit and is 31
44 if(pos > 0)
45 {
46 // parse last bit and check it's between 0 and 31
47 bool ok = false;
48 last = input.left(pos).toInt(&ok);
49 if(!ok || last < 0 || last >= 32)
50 return Invalid;
51 }
52 else
53 last = 31;
54 // parse first bit
55 if(pos < input.size() - 1)
56 {
57 bool ok = false;
58 first = input.mid(pos + 1).toInt(&ok);
59 if(!ok || first < 0 || first > last)
60 return Invalid;
61 }
62 // if input ends with ':', first bit is implicit and is 0
63 else if(pos == input.size() - 1)
64 first = 0;
65 // if there no ':', first=last
66 else
67 first = last;
68 return Acceptable;
69}
70
71/**
72 * SocFieldValidator
73 */
74
75SocFieldValidator::SocFieldValidator(QObject *parent)
76 :QValidator(parent)
77{
78 m_field.first_bit = 0;
79 m_field.last_bit = 31;
80}
81
82SocFieldValidator::SocFieldValidator(const soc_reg_field_t& field, QObject *parent)
83 :QValidator(parent), m_field(field)
84{
85}
86
87void SocFieldValidator::fixup(QString& input) const
88{
89 input = input.trimmed();
90}
91
92QValidator::State SocFieldValidator::validate(QString& input, int& pos) const
93{
94 Q_UNUSED(pos);
95 soc_word_t val;
96 State state = parse(input, val);
97 return state;
98}
99
100QValidator::State SocFieldValidator::parse(const QString& input, soc_word_t& val) const
101{
102 // the empty string is always intermediate
103 if(input.size() == 0)
104 return Intermediate;
105 // first check named values
106 State state = Invalid;
107 foreach(const soc_reg_field_value_t& value, m_field.value)
108 {
109 QString name = QString::fromLocal8Bit(value.name.c_str());
110 // cannot be a substring if too long or empty
111 if(input.size() > name.size())
112 continue;
113 // check equal string
114 if(input == name)
115 {
116 state = Acceptable;
117 val = value.value;
118 break;
119 }
120 // check substring
121 if(name.startsWith(input))
122 state = Intermediate;
123 }
124 // early return for exact match
125 if(state == Acceptable)
126 return state;
127 // do a few special cases for convenience
128 if(input.compare("0x", Qt::CaseInsensitive) == 0 ||
129 input.compare("0b", Qt::CaseInsensitive) == 0)
130 return Intermediate;
131 // try by parsing
132 unsigned basis, pos;
133 if(input.size() >= 2 && input.startsWith("0x", Qt::CaseInsensitive))
134 {
135 basis = 16;
136 pos = 2;
137 }
138 else if(input.size() >= 2 && input.startsWith("0b", Qt::CaseInsensitive))
139 {
140 basis = 2;
141 pos = 2;
142 }
143 else if(input.size() >= 2 && input.startsWith("0"))
144 {
145 basis = 8;
146 pos = 1;
147 }
148 else
149 {
150 basis = 10;
151 pos = 0;
152 }
153 bool ok = false;
154 unsigned long v = input.mid(pos).toULong(&ok, basis);
155 // if not ok, return result of name parsing
156 if(!ok)
157 return state;
158 // if ok, check if it fits in the number of bits
159 unsigned nr_bits = m_field.last_bit - m_field.first_bit + 1;
160 unsigned long max = nr_bits == 32 ? 0xffffffff : (1 << nr_bits) - 1;
161 if(v <= max)
162 {
163 val = v;
164 return Acceptable;
165 }
166
167 return state;
168}
169
170/**
171 * RegLineEdit
172 */
173RegLineEdit::RegLineEdit(QWidget *parent)
174 :QWidget(parent)
175{
176 m_layout = new QHBoxLayout(this);
177 m_button = new QToolButton(this);
178 m_button->setCursor(Qt::ArrowCursor);
179 m_button->setStyleSheet("QToolButton { font-weight: bold; color: white; background: black; }");
180 m_button->setPopupMode(QToolButton::InstantPopup);
181 m_edit = new QLineEdit(this);
182 m_layout->addWidget(m_button);
183 m_layout->addWidget(m_edit);
184 m_menu = new QMenu(this);
185 connect(m_menu->addAction("Write"), SIGNAL(triggered()), this, SLOT(OnWriteAct()));
186 connect(m_menu->addAction("Set"), SIGNAL(triggered()), this, SLOT(OnSetAct()));
187 connect(m_menu->addAction("Clear"), SIGNAL(triggered()), this, SLOT(OnClearAct()));
188 connect(m_menu->addAction("Toggle"), SIGNAL(triggered()), this, SLOT(OnToggleAct()));
189 EnableSCT(false);
190 SetReadOnly(false);
191 ShowMode(true);
192 SetMode(Write);
193}
194
195void RegLineEdit::SetReadOnly(bool ro)
196{
197 m_edit->setReadOnly(ro);
198 m_readonly = ro;
199 ShowMode(!ro);
200}
201
202void RegLineEdit::EnableSCT(bool en)
203{
204 m_has_sct = en;
205 if(!m_has_sct)
206 {
207 m_button->setMenu(0);
208 SetMode(Write);
209 }
210 else
211 m_button->setMenu(m_menu);
212}
213
214RegLineEdit::~RegLineEdit()
215{
216}
217
218QLineEdit *RegLineEdit::GetLineEdit()
219{
220 return m_edit;
221}
222
223void RegLineEdit::ShowMode(bool show)
224{
225 if(show)
226 m_button->show();
227 else
228 m_button->hide();
229}
230
231void RegLineEdit::OnWriteAct()
232{
233 SetMode(Write);
234}
235
236void RegLineEdit::OnSetAct()
237{
238 SetMode(Set);
239}
240
241void RegLineEdit::OnClearAct()
242{
243 SetMode(Clear);
244}
245
246void RegLineEdit::OnToggleAct()
247{
248 SetMode(Toggle);
249}
250
251void RegLineEdit::SetMode(EditMode mode)
252{
253 m_mode = mode;
254 switch(m_mode)
255 {
256 case Write: m_button->setText("WR"); break;
257 case Set: m_button->setText("SET"); break;
258 case Clear: m_button->setText("CLR"); break;
259 case Toggle: m_button->setText("TOG"); break;
260 default: break;
261 }
262}
263
264RegLineEdit::EditMode RegLineEdit::GetMode()
265{
266 return m_mode;
267}
268
269void RegLineEdit::setText(const QString& text)
270{
271 m_edit->setText(text);
272}
273
274QString RegLineEdit::text() const
275{
276 return m_edit->text();
277}
278
279/**
280 * SocFieldItemDelegate
281 */
282
283QString SocFieldItemDelegate::displayText(const QVariant& value, const QLocale& locale) const
284{
285 if(value.type() == QVariant::UInt)
286 return QString("0x%1").arg(value.toUInt(), (m_bitcount + 3) / 4, 16, QChar('0'));
287 else
288 return QStyledItemDelegate::displayText(value, locale);
289}
290
291/**
292 * SocFieldEditor
293 */
294SocFieldEditor::SocFieldEditor(const soc_reg_field_t& field, QWidget *parent)
295 :QLineEdit(parent), m_reg_field(field)
296{
297 m_validator = new SocFieldValidator(field);
298 setValidator(m_validator);
299}
300
301SocFieldEditor::~SocFieldEditor()
302{
303 delete m_validator;
304}
305
306uint SocFieldEditor::field() const
307{
308 soc_word_t v;
309 /* in case validator fails to parse, return old value */
310 if(m_validator->parse(text(), v) == QValidator::Acceptable)
311 return v;
312 else
313 return m_field;
314}
315
316void SocFieldEditor::setField(uint field)
317{
318 m_field = field;
319 int digits = (m_reg_field.last_bit - m_reg_field.first_bit + 4) / 4;
320 setText(QString("0x%1").arg(field, digits, 16, QChar('0')));
321}
322
323/**
324 * SocFieldEditorCreator
325 */
326QWidget *SocFieldEditorCreator::createWidget(QWidget *parent) const
327{
328 return new SocFieldEditor(m_field, parent);
329}
330
331QByteArray SocFieldEditorCreator::valuePropertyName() const
332{
333 return QByteArray("field");
334}
335
336/**
337 * RegSexyDisplay
338 */
339RegSexyDisplay::RegSexyDisplay(const SocRegRef& reg, QWidget *parent)
340 :QWidget(parent), m_reg(reg)
341{
342 m_size = QSize();
343}
344
345int RegSexyDisplay::separatorSize() const
346{
347 return 1;
348}
349
350int RegSexyDisplay::marginSize() const
351{
352 return fontMetrics().height() / 3;
353}
354
355int RegSexyDisplay::textSep() const
356{
357 return marginSize() / 2;
358}
359
360int RegSexyDisplay::headerHeight() const
361{
362 return 2 * marginSize() + textSep() + 2 * fontMetrics().height();
363}
364
365int RegSexyDisplay::columnWidth() const
366{
367 return 2 * marginSize() + fontMetrics().height();
368}
369
370int RegSexyDisplay::maxContentHeight() const
371{
372 int max = 0;
373 QFontMetrics metrics = fontMetrics();
374 for(size_t i = 0; i < m_reg.GetReg().field.size(); i++)
375 {
376 QString s = QString::fromStdString(m_reg.GetReg().field[i].name);
377 // add extra spaces arounds
378 s = " " + s + " ";
379 max = qMax(max, metrics.boundingRect(s).width());
380 }
381 return 2 * marginSize() + max;
382}
383
384int RegSexyDisplay::gapHeight() const
385{
386 return marginSize() / 2;
387}
388
389QSize RegSexyDisplay::minimumSizeHint() const
390{
391 /* cache computation because it's expensive */
392 if(m_size.isValid())
393 return m_size;
394 /* width: display 32 columns + 33 vertical separators */
395 m_size.setWidth(32 * columnWidth() + 33 * separatorSize());
396 /* height: one separator + two digits + one separator + margin + separator
397 * + names + separator */
398 m_size.setHeight(4 * separatorSize() + headerHeight() + gapHeight() + maxContentHeight());
399 return m_size;
400}
401
402QSize RegSexyDisplay::sizeHint() const
403{
404 return minimumSizeHint();
405}
406
407void RegSexyDisplay::paintEvent(QPaintEvent *event)
408{
409 // FIXME could be optimised with QStaticText
410 Q_UNUSED(event);
411 int txt_h = fontMetrics().height();
412 int sep_sz = separatorSize();
413 int w = width();
414 int h = height() - 1;
415 int col_w = (w - 33 * sep_sz) / 32;
416 int hdr_h = headerHeight();
417 int gap_h = gapHeight();
418 int tot_w = 33 * sep_sz + 32 * col_w;
419 int margin = marginSize();
420 int txt_sep = textSep();
421 int tot_hdr_sz = 2 * sep_sz + hdr_h;
422 // computer xshift
423 int x_shift = (w - tot_w) / 2;
424#define ith_col_x(i) (x_shift + (i) * (sep_sz + col_w))
425
426 QPainter painter(this);
427 QBrush back_brush = palette().base();
428 QBrush line_brush = palette().dark();
429
430 // fill interesting zone with base
431 painter.fillRect(x_shift, 0, tot_w, h, back_brush);
432
433 // draw top and bottom lines
434 painter.setPen(QPen(palette().dark(), sep_sz));
435 painter.fillRect(x_shift, 0, tot_w, sep_sz, line_brush);
436 painter.fillRect(x_shift, h - sep_sz, tot_w, sep_sz, line_brush);
437 // draw intemediate lines
438 for(int i = 0; i <= 32; i++)
439 painter.fillRect(ith_col_x(i), 0, sep_sz, 2 * sep_sz + hdr_h, line_brush);
440 // draw bottom header lines
441 painter.fillRect(ith_col_x(0), sep_sz + hdr_h, tot_w, sep_sz, line_brush);
442 painter.fillRect(ith_col_x(0), tot_hdr_sz + gap_h, tot_w, sep_sz, line_brush);
443 // redraw some lines but wider
444 for(int i = 4; i < 32; i += 4)
445 painter.fillRect(ith_col_x(i) - sep_sz, 0, 3 * sep_sz, tot_hdr_sz, line_brush);
446 // draw numbers in the header
447 painter.setPen(palette().brush(QPalette::ButtonText).color());
448 for(int i = 0; i < 32; i++)
449 {
450 QRect r(ith_col_x(i), sep_sz + margin, col_w, txt_h);
451 painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) / 10));
452 r.translate(0, txt_h + txt_sep);
453 painter.drawText(r, Qt::AlignCenter, QString("%1").arg((31 - i) % 10));
454 }
455 // display content
456 for(size_t i = 0; i < m_reg.GetReg().field.size(); i++)
457 {
458 const soc_reg_field_t& field = m_reg.GetReg().field[i];
459 QRect r(QPoint(ith_col_x(31 - field.last_bit) + sep_sz, tot_hdr_sz),
460 QPoint(ith_col_x(32 - field.first_bit), h - sep_sz));
461 painter.fillRect(r.x() - sep_sz, r.y(), sep_sz, r.height(), line_brush);
462 painter.fillRect(r.right(), r.y(), sep_sz, r.height(), line_brush);
463 r.setY(r.y() + gap_h + sep_sz);
464 // draw rotated text
465 painter.save();
466 painter.translate(r.bottomLeft());
467 painter.rotate(-90);
468 //painter.fillRect(QRect(0, 0, r.height(), r.width()), QBrush(Qt::red));
469 QRect r2(0, 0, r.height(), r.width());
470 painter.drawText(r2, Qt::AlignCenter, QString::fromStdString(field.name));
471 painter.restore();
472 }
473#undef ith_col_x
474}
475
476/**
477 * GrowingTextEdit
478 */
479GrowingTextEdit::GrowingTextEdit(QWidget *parent)
480 :QTextEdit(parent)
481{
482 connect(this, SIGNAL(textChanged()), this, SLOT(TextChanged()));
483 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
484 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
485}
486
487void GrowingTextEdit::TextChanged()
488{
489 int content_size = document()->documentLayout()->documentSize().height();
490 content_size = qMax(content_size, fontMetrics().height());
491 setFixedHeight(content_size + contentsMargins().top() + contentsMargins().bottom());
492}
493
494/**
495 * GrowingTableWidget
496 */
497GrowingTableWidget::GrowingTableWidget(QWidget *parent)
498 :QTableWidget(parent)
499{
500 connect(model(), SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)),
501 this, SLOT(DataChanged(const QModelIndex&, const QModelIndex&)));
502}
503
504void GrowingTableWidget::DataChanged(const QModelIndex& tl, const QModelIndex& br)
505{
506 Q_UNUSED(tl);
507 Q_UNUSED(br);
508 resizeRowsToContents();
509 resizeColumnsToContents();
510 int h = contentsMargins().top() + contentsMargins().bottom();
511 h += horizontalHeader()->height();
512 for(int i = 0; i < rowCount(); i++)
513 h += rowHeight(i);
514 setMinimumHeight(h);
515}
516
517/**
518 * MyTextEditor
519 */
520MyTextEditor::MyTextEditor(QWidget *parent)
521 :QWidget(parent)
522{
523 QVBoxLayout *layout = new QVBoxLayout;
524 m_toolbar = new QToolBar(this);
525 m_edit = new QTextEdit(this);
526 layout->addWidget(m_toolbar, 0);
527 layout->addWidget(m_edit, 1);
528 setLayout(layout);
529 setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
530
531 m_edit->setAcceptRichText(false);
532 m_edit->setAutoFormatting(QTextEdit::AutoAll);
533
534 m_bold_button = new QToolButton(this);
535 m_bold_button->setIcon(QIcon::fromTheme("format-text-bold"));
536 m_bold_button->setText("bold");
537 m_bold_button->setCheckable(true);
538
539 m_italic_button = new QToolButton(this);
540 m_italic_button->setIcon(QIcon::fromTheme("format-text-italic"));
541 m_italic_button->setText("italic");
542 m_italic_button->setCheckable(true);
543
544 m_underline_button = new QToolButton(this);
545 m_underline_button->setIcon(QIcon::fromTheme("format-text-underline"));
546 m_underline_button->setText("underline");
547 m_underline_button->setCheckable(true);
548
549 m_toolbar->addWidget(m_bold_button);
550 m_toolbar->addWidget(m_italic_button);
551 m_toolbar->addWidget(m_underline_button);
552
553 connect(m_bold_button, SIGNAL(toggled(bool)), this, SLOT(OnTextBold(bool)));
554 connect(m_italic_button, SIGNAL(toggled(bool)), this, SLOT(OnTextItalic(bool)));
555 connect(m_underline_button, SIGNAL(toggled(bool)), this, SLOT(OnTextUnderline(bool)));
556 connect(m_edit, SIGNAL(textChanged()), this, SLOT(OnInternalTextChanged()));
557 connect(m_edit, SIGNAL(currentCharFormatChanged(const QTextCharFormat&)),
558 this, SLOT(OnCharFormatChanged(const QTextCharFormat&)));
559
560 SetGrowingMode(false);
561 SetReadOnly(false);
562}
563
564void MyTextEditor::SetReadOnly(bool en)
565{
566 m_read_only = en;
567 if(en)
568 m_toolbar->hide();
569 else
570 m_toolbar->hide();
571 m_edit->setReadOnly(en);
572}
573
574void MyTextEditor::SetGrowingMode(bool en)
575{
576 m_growing_mode = en;
577 if(en)
578 {
579 m_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
580 m_edit->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
581 OnTextChanged();
582 }
583 else
584 {
585 m_edit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
586 m_edit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
587 }
588}
589
590void MyTextEditor::OnInternalTextChanged()
591{
592 if(m_growing_mode)
593 {
594 int content_size = m_edit->document()->documentLayout()->documentSize().height();
595 content_size = qMax(content_size, m_edit->fontMetrics().height());
596 m_edit->setMinimumHeight(content_size + m_edit->contentsMargins().top() +
597 m_edit->contentsMargins().bottom());
598 }
599 emit OnTextChanged();
600}
601
602void MyTextEditor::OnTextBold(bool checked)
603{
604 QTextCursor cursor = m_edit->textCursor();
605 QTextCharFormat fmt = cursor.charFormat();
606 fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal);
607 cursor.setCharFormat(fmt);
608 m_edit->setTextCursor(cursor);
609}
610
611void MyTextEditor::OnTextItalic(bool checked)
612{
613 QTextCursor cursor = m_edit->textCursor();
614 QTextCharFormat fmt = cursor.charFormat();
615 fmt.setFontItalic(checked);
616 cursor.setCharFormat(fmt);
617 m_edit->setTextCursor(cursor);
618}
619
620void MyTextEditor::OnTextUnderline(bool checked)
621{
622 QTextCursor cursor = m_edit->textCursor();
623 QTextCharFormat fmt = cursor.charFormat();
624 fmt.setFontUnderline(checked);
625 cursor.setCharFormat(fmt);
626 m_edit->setTextCursor(cursor);
627}
628
629void MyTextEditor::OnCharFormatChanged(const QTextCharFormat& fmt)
630{
631 /* NOTE: changing the button states programmaticaly doesn't trigger
632 * the toggled() signals, otherwise it would result in a loop
633 * between this function and OnText{Bold,Italic,Underline,...} */
634 m_bold_button->setChecked(fmt.fontWeight() > QFont::Normal);
635 m_italic_button->setChecked(fmt.fontItalic());
636 m_underline_button->setChecked(fmt.fontUnderline());
637}
638
639void MyTextEditor::SetTextHtml(const QString& text)
640{
641 m_edit->setHtml(text);
642}
643
644QString MyTextEditor::GetTextHtml()
645{
646 return m_edit->toPlainText();
647}
648
649bool MyTextEditor::IsModified()
650{
651 return m_edit->document()->isModified();
652}
653
654/**
655 * MySwitchableTextEditor
656 */
657MySwitchableTextEditor::MySwitchableTextEditor(QWidget *parent)
658 :QWidget(parent)
659{
660 QVBoxLayout *layout = new QVBoxLayout(this);
661 m_edit = new MyTextEditor(this);
662 m_label = new QLabel(this);
663 m_label->setTextFormat(Qt::RichText);
664 m_label->setAlignment(Qt::AlignTop);
665 m_line = new QLineEdit(this);
666
667 layout->addWidget(m_label);
668 layout->addWidget(m_edit);
669 layout->addWidget(m_line);
670
671 setLayout(layout);
672
673 m_editor_mode = false;
674 m_line_mode = false;
675 UpdateVisibility();
676}
677
678void MySwitchableTextEditor::SetEditorMode(bool edit)
679{
680 if(edit == m_editor_mode)
681 return;
682 QString text = GetTextHtml();
683 m_editor_mode = edit;
684 UpdateVisibility();
685 SetTextHtml(text);
686}
687
688QString MySwitchableTextEditor::GetTextHtml()
689{
690 if(m_editor_mode)
691 return m_line_mode ? m_line->text() : m_edit->GetTextHtml();
692 else
693 return m_label->text();
694}
695
696void MySwitchableTextEditor::SetTextHtml(const QString& text)
697{
698 if(m_editor_mode)
699 {
700 if(m_line_mode)
701 m_line->setText(text);
702 else
703 m_edit->SetTextHtml(text);
704 }
705 else
706 m_label->setText(text);
707}
708
709MyTextEditor *MySwitchableTextEditor::GetEditor()
710{
711 return m_edit;
712}
713
714void MySwitchableTextEditor::SetLineMode(bool en)
715{
716 if(m_line_mode == en)
717 return;
718 QString text = GetTextHtml();
719 m_line_mode = en;
720 SetTextHtml(text);
721 UpdateVisibility();
722}
723
724QLineEdit *MySwitchableTextEditor::GetLineEdit()
725{
726 return m_line;
727}
728
729void MySwitchableTextEditor::UpdateVisibility()
730{
731 m_label->setVisible(!m_editor_mode);
732 m_edit->setVisible(m_editor_mode && !m_line_mode);
733 m_line->setVisible(m_editor_mode && m_line_mode);
734}
735
736QLabel *MySwitchableTextEditor::GetLabel()
737{
738 return m_label;
739}
740
741bool MySwitchableTextEditor::IsModified()
742{
743 if(!m_editor_mode)
744 return false;
745 return m_line_mode ? m_line->isModified() : m_edit->IsModified();
746}
diff --git a/utils/regtools/qeditor/aux.h b/utils/regtools/qeditor/aux.h
new file mode 100644
index 0000000000..d6a572826c
--- /dev/null
+++ b/utils/regtools/qeditor/aux.h
@@ -0,0 +1,227 @@
1#ifndef AUX_H
2#define AUX_H
3
4#include <QEvent>
5#include <QPaintEvent>
6#include <QLineEdit>
7#include <QValidator>
8#include <QToolButton>
9#include <QMenu>
10#include <QHBoxLayout>
11#include <QTextEdit>
12#include <QTableWidget>
13#include <QToolBar>
14#include <QLabel>
15#include <QHBoxLayout>
16#include <QItemEditorCreatorBase>
17#include <QStyledItemDelegate>
18#include "backend.h"
19
20class SocBitRangeValidator : public QValidator
21{
22 Q_OBJECT
23public:
24 SocBitRangeValidator(QObject *parent = 0);
25
26 virtual void fixup(QString& input) const;
27 virtual State validate(QString& input, int& pos) const;
28 /* validate and return the interpreted value */
29 State parse(const QString& input, int& last_bit, int& first_bit) const;
30};
31
32class SocFieldValidator : public QValidator
33{
34 Q_OBJECT
35public:
36 SocFieldValidator(QObject *parent = 0);
37 SocFieldValidator(const soc_reg_field_t& field, QObject *parent = 0);
38
39 virtual void fixup(QString& input) const;
40 virtual State validate(QString& input, int& pos) const;
41 /* validate and return the interpreted value */
42 State parse(const QString& input, soc_word_t& val) const;
43
44protected:
45 soc_reg_field_t m_field;
46};
47
48class RegLineEdit : public QWidget
49{
50 Q_OBJECT
51public:
52 enum EditMode
53 {
54 Write, Set, Clear, Toggle
55 };
56
57 RegLineEdit(QWidget *parent = 0);
58 ~RegLineEdit();
59 void SetReadOnly(bool ro);
60 void EnableSCT(bool en);
61 void SetMode(EditMode mode);
62 EditMode GetMode();
63 QLineEdit *GetLineEdit();
64 void setText(const QString& text);
65 QString text() const;
66
67 Q_PROPERTY(QString text READ text WRITE setText USER true)
68
69protected slots:
70 void OnWriteAct();
71 void OnSetAct();
72 void OnClearAct();
73 void OnToggleAct();
74protected:
75 void ShowMode(bool show);
76 void DoAutoHide();
77
78 QHBoxLayout *m_layout;
79 QToolButton *m_button;
80 QLineEdit *m_edit;
81 EditMode m_mode;
82 bool m_has_sct;
83 bool m_readonly;
84 QMenu *m_menu;
85};
86
87class SocFieldItemDelegate : public QStyledItemDelegate
88{
89public:
90 SocFieldItemDelegate(QObject *parent = 0):QStyledItemDelegate(parent), m_bitcount(32) {}
91 SocFieldItemDelegate(const soc_reg_field_t& field, QObject *parent = 0)
92 :QStyledItemDelegate(parent), m_bitcount(field.last_bit - field.first_bit + 1) {}
93
94 virtual QString displayText(const QVariant& value, const QLocale& locale) const;
95protected:
96 int m_bitcount;
97};
98
99class SocFieldEditor : public QLineEdit
100{
101 Q_OBJECT
102 Q_PROPERTY(uint field READ field WRITE setField USER true)
103public:
104 SocFieldEditor(const soc_reg_field_t& field, QWidget *parent = 0);
105 virtual ~SocFieldEditor();
106
107 uint field() const;
108 void setField(uint field);
109
110protected:
111 SocFieldValidator *m_validator;
112 uint m_field;
113 soc_reg_field_t m_reg_field;
114};
115
116class SocFieldEditorCreator : public QItemEditorCreatorBase
117{
118public:
119 SocFieldEditorCreator() { m_field.first_bit = 0; m_field.last_bit = 31; }
120 SocFieldEditorCreator(const soc_reg_field_t& field):m_field(field) {}
121
122 virtual QWidget *createWidget(QWidget *parent) const;
123 virtual QByteArray valuePropertyName() const;
124
125protected:
126 soc_reg_field_t m_field;
127};
128
129class RegSexyDisplay : public QWidget
130{
131 Q_OBJECT
132public:
133 RegSexyDisplay(const SocRegRef& reg, QWidget *parent = 0);
134
135 QSize minimumSizeHint() const;
136 QSize sizeHint() const;
137
138protected:
139 int marginSize() const;
140 int separatorSize() const;
141 int columnWidth() const;
142 int headerHeight() const;
143 int gapHeight() const;
144 int maxContentHeight() const;
145 int textSep() const;
146 void paintEvent(QPaintEvent *event);
147
148private:
149 SocRegRef m_reg;
150 mutable QSize m_size;
151};
152
153class GrowingTextEdit : public QTextEdit
154{
155 Q_OBJECT
156public:
157 GrowingTextEdit(QWidget *parent = 0);
158
159protected slots:
160 void TextChanged();
161};
162
163class GrowingTableWidget : public QTableWidget
164{
165 Q_OBJECT
166public:
167 GrowingTableWidget(QWidget *parent = 0);
168
169protected slots:
170 void DataChanged(const QModelIndex& tl, const QModelIndex& br);
171};
172
173class MyTextEditor : public QWidget
174{
175 Q_OBJECT
176public:
177 MyTextEditor(QWidget *parent = 0);
178 void SetGrowingMode(bool en);
179 void SetReadOnly(bool ro);
180 void SetTextHtml(const QString& text);
181 QString GetTextHtml();
182 bool IsModified();
183signals:
184 void OnTextChanged();
185
186protected slots:
187 void OnInternalTextChanged();
188 void OnTextBold(bool checked);
189 void OnTextItalic(bool checked);
190 void OnTextUnderline(bool checked);
191 void OnCharFormatChanged(const QTextCharFormat& fmt);
192
193protected:
194 bool m_growing_mode;
195 bool m_read_only;
196 QToolBar *m_toolbar;
197 QTextEdit *m_edit;
198 QToolButton *m_bold_button;
199 QToolButton *m_italic_button;
200 QToolButton *m_underline_button;
201};
202
203class MySwitchableTextEditor : public QWidget
204{
205 Q_OBJECT
206public:
207 MySwitchableTextEditor(QWidget *parent = 0);
208 QString GetTextHtml();
209 void SetTextHtml(const QString& text);
210 void SetEditorMode(bool en);
211 MyTextEditor *GetEditor();
212 QLineEdit *GetLineEdit();
213 QLabel *GetLabel();
214 void SetLineMode(bool en);
215 bool IsModified();
216
217protected:
218 void UpdateVisibility();
219
220 bool m_editor_mode;
221 bool m_line_mode;
222 QLabel *m_label;
223 MyTextEditor *m_edit;
224 QLineEdit *m_line;
225};
226
227#endif /* AUX_H */
diff --git a/utils/regtools/qeditor/backend.cpp b/utils/regtools/qeditor/backend.cpp
index eebda31989..204c160054 100644
--- a/utils/regtools/qeditor/backend.cpp
+++ b/utils/regtools/qeditor/backend.cpp
@@ -5,6 +5,36 @@
5#include "backend.h" 5#include "backend.h"
6 6
7/** 7/**
8 * SocFile
9 */
10SocFile::SocFile()
11 :m_valid(false)
12{
13}
14
15SocFile::SocFile(const QString& filename)
16 :m_filename(filename)
17{
18 m_valid = soc_desc_parse_xml(filename.toStdString(), m_soc);
19 soc_desc_normalize(m_soc);
20}
21
22bool SocFile::IsValid()
23{
24 return m_valid;
25}
26
27SocRef SocFile::GetSocRef()
28{
29 return SocRef(this);
30}
31
32QString SocFile::GetFilename()
33{
34 return m_filename;
35}
36
37/**
8 * Backend 38 * Backend
9 */ 39 */
10 40
@@ -12,33 +42,31 @@ Backend::Backend()
12{ 42{
13} 43}
14 44
15QStringList Backend::GetSocNameList() 45
46QList< SocFileRef > Backend::GetSocFileList()
16{ 47{
17 QStringList sl; 48 QList< SocFileRef > list;
18 foreach(const soc_t& soc, m_socs) 49 for(std::list< SocFile >::iterator it = m_socs.begin(); it != m_socs.end(); ++it)
19 sl.append(QString(soc.name.c_str())); 50 list.append(SocFileRef(&(*it)));
20 return sl; 51 return list;
21} 52}
22 53
23bool Backend::GetSocByName(const QString& name, SocRef& s) 54QList< SocRef > Backend::GetSocList()
24{ 55{
25 for(std::list< soc_t >::iterator it = m_socs.begin(); it != m_socs.end(); ++it) 56 QList< SocRef > list;
26 if(it->name == name.toStdString()) 57 for(std::list< SocFile >::iterator it = m_socs.begin(); it != m_socs.end(); ++it)
27 { 58 list.append(it->GetSocRef());
28 s = SocRef(&(*it)); 59 return list;
29 return true;
30 }
31 return false;
32} 60}
33 61
34bool Backend::LoadSocDesc(const QString& filename) 62bool Backend::LoadSocDesc(const QString& filename)
35{ 63{
36 std::vector< soc_t > new_socs; 64 SocFile f(filename);
37 bool ret = soc_desc_parse_xml(filename.toStdString(), new_socs); 65 if(!f.IsValid())
38 for(size_t i = 0; i < new_socs.size(); i++) 66 return false;
39 m_socs.push_back(new_socs[i]); 67 m_socs.push_back(f);
40 emit OnSocListChanged(); 68 emit OnSocListChanged();
41 return ret; 69 return true;
42} 70}
43 71
44IoBackend *Backend::CreateFileIoBackend(const QString& filename) 72IoBackend *Backend::CreateFileIoBackend(const QString& filename)
@@ -321,7 +349,7 @@ HWStubBackendHelper::HWStubBackendHelper()
321 if(m_hotplug) 349 if(m_hotplug)
322 { 350 {
323 m_hotplug = LIBUSB_SUCCESS == libusb_hotplug_register_callback( 351 m_hotplug = LIBUSB_SUCCESS == libusb_hotplug_register_callback(
324 NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT, 352 NULL, (libusb_hotplug_event)(LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED | LIBUSB_HOTPLUG_EVENT_DEVICE_LEFT),
325 LIBUSB_HOTPLUG_ENUMERATE, HWSTUB_USB_VID, HWSTUB_USB_PID, HWSTUB_CLASS, 353 LIBUSB_HOTPLUG_ENUMERATE, HWSTUB_USB_VID, HWSTUB_USB_PID, HWSTUB_CLASS,
326 &HWStubBackendHelper::HotPlugCallback, reinterpret_cast< void* >(this), &m_hotplug_handle); 354 &HWStubBackendHelper::HotPlugCallback, reinterpret_cast< void* >(this), &m_hotplug_handle);
327 } 355 }
@@ -364,6 +392,7 @@ void HWStubBackendHelper::OnHotPlug(bool arrived, struct libusb_device *dev)
364int HWStubBackendHelper::HotPlugCallback(struct libusb_context *ctx, struct libusb_device *dev, 392int HWStubBackendHelper::HotPlugCallback(struct libusb_context *ctx, struct libusb_device *dev,
365 libusb_hotplug_event event, void *user_data) 393 libusb_hotplug_event event, void *user_data)
366{ 394{
395 Q_UNUSED(ctx);
367 HWStubBackendHelper *helper = reinterpret_cast< HWStubBackendHelper* >(user_data); 396 HWStubBackendHelper *helper = reinterpret_cast< HWStubBackendHelper* >(user_data);
368 switch(event) 397 switch(event)
369 { 398 {
diff --git a/utils/regtools/qeditor/backend.h b/utils/regtools/qeditor/backend.h
index 939ed9529f..a813f5929f 100644
--- a/utils/regtools/qeditor/backend.h
+++ b/utils/regtools/qeditor/backend.h
@@ -5,10 +5,11 @@
5#include <QStringList> 5#include <QStringList>
6#include <QMap> 6#include <QMap>
7#include <QVector> 7#include <QVector>
8#include "soc_desc.hpp" 8#include <QMetaType>
9#ifdef HAVE_HWSTUB 9#ifdef HAVE_HWSTUB
10#include "hwstub.h" 10#include "hwstub.h"
11#endif 11#endif
12#include "soc.h"
12 13
13class IoBackend : public QObject 14class IoBackend : public QObject
14{ 15{
@@ -62,18 +63,18 @@ class DummyIoBackend : public IoBackend
62public: 63public:
63 DummyIoBackend() {} 64 DummyIoBackend() {}
64 65
65 virtual bool SupportAccess(AccessType type) { (void) type; return false; } 66 virtual bool SupportAccess(AccessType type) { Q_UNUSED(type); return false; }
66 virtual QString GetSocName() { return ""; } 67 virtual QString GetSocName() { return ""; }
67 virtual bool ReadRegister(const QString& name, soc_word_t& value) 68 virtual bool ReadRegister(const QString& name, soc_word_t& value)
68 { (void) name; (void) value; return false; } 69 { Q_UNUSED(name); Q_UNUSED(value); return false; }
69 virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) 70 virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value)
70 { (void) addr; (void) value; return false; } 71 { Q_UNUSED(addr); Q_UNUSED(value); return false; }
71 virtual bool Reload() { return false; } 72 virtual bool Reload() { return false; }
72 virtual bool IsReadOnly() { return true; } 73 virtual bool IsReadOnly() { return true; }
73 virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode) 74 virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode)
74 { (void) name; (void) value; (void) mode; return false; } 75 { Q_UNUSED(name); Q_UNUSED(value); Q_UNUSED(mode); return false; }
75 virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode) 76 virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode)
76 { (void) addr; (void) value; (void) mode; return false; } 77 { Q_UNUSED(addr); Q_UNUSED(value); Q_UNUSED(mode); return false; }
77 virtual bool IsDirty() { return false; } 78 virtual bool IsDirty() { return false; }
78 virtual bool Commit() { return false; } 79 virtual bool Commit() { return false; }
79}; 80};
@@ -90,12 +91,12 @@ public:
90 virtual QString GetSocName(); 91 virtual QString GetSocName();
91 virtual bool ReadRegister(const QString& name, soc_word_t& value); 92 virtual bool ReadRegister(const QString& name, soc_word_t& value);
92 virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value) 93 virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value)
93 { (void) addr; (void) value; return false; } 94 { Q_UNUSED(addr); Q_UNUSED(value); return false; }
94 virtual bool Reload(); 95 virtual bool Reload();
95 virtual bool IsReadOnly() { return m_readonly; } 96 virtual bool IsReadOnly() { return m_readonly; }
96 virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode); 97 virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode);
97 virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode) 98 virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode)
98 { (void) addr; (void) value; (void) mode; return false; } 99 { Q_UNUSED(addr); Q_UNUSED(value); Q_UNUSED(mode); return false; }
99 virtual bool IsDirty() { return m_dirty; } 100 virtual bool IsDirty() { return m_dirty; }
100 virtual bool Commit(); 101 virtual bool Commit();
101 102
@@ -149,12 +150,12 @@ public:
149 virtual bool SupportAccess(AccessType type) { return type == ByAddress; } 150 virtual bool SupportAccess(AccessType type) { return type == ByAddress; }
150 virtual QString GetSocName(); 151 virtual QString GetSocName();
151 virtual bool ReadRegister(const QString& name, soc_word_t& value) 152 virtual bool ReadRegister(const QString& name, soc_word_t& value)
152 { (void) name; (void) value; return false; } 153 { Q_UNUSED(name); Q_UNUSED(value); return false; }
153 virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value); 154 virtual bool ReadRegister(soc_addr_t addr, soc_word_t& value);
154 virtual bool Reload(); 155 virtual bool Reload();
155 virtual bool IsReadOnly() { return false; } 156 virtual bool IsReadOnly() { return false; }
156 virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode) 157 virtual bool WriteRegister(const QString& name, soc_word_t value, WriteMode mode)
157 { (void) name; (void) value; (void) mode; return false; } 158 { Q_UNUSED(name); Q_UNUSED(value); Q_UNUSED(mode); return false; }
158 virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode); 159 virtual bool WriteRegister(soc_addr_t addr, soc_word_t value, WriteMode mode);
159 virtual bool IsDirty() { return false; } 160 virtual bool IsDirty() { return false; }
160 virtual bool Commit() { return true; } 161 virtual bool Commit() { return true; }
@@ -191,16 +192,48 @@ protected:
191}; 192};
192#endif 193#endif
193 194
194class SocRef 195class SocRef;
196
197class SocFile
198{
199public:
200 SocFile();
201 SocFile(const QString& filename);
202 bool IsValid();
203
204 SocRef GetSocRef();
205 QString GetFilename();
206 soc_t& GetSoc() { return m_soc; }
207
208protected:
209 bool m_valid;
210 QString m_filename;
211 soc_t m_soc;
212};
213
214class SocFileRef
195{ 215{
196public: 216public:
197 SocRef():m_soc(0) {} 217 SocFileRef():m_socfile(0) {}
198 SocRef(const soc_t *soc):m_soc(soc) {} 218 SocFileRef(SocFile *file):m_socfile(file) {}
199 const soc_t& GetSoc() const { return *m_soc; } 219 SocFile *GetSocFile() const { return m_socfile; }
220
200protected: 221protected:
201 const soc_t *m_soc; 222 SocFile *m_socfile;
202}; 223};
203 224
225Q_DECLARE_METATYPE(SocFileRef)
226
227class SocRef : public SocFileRef
228{
229public:
230 SocRef() {}
231 SocRef(SocFile *file):SocFileRef(file) {}
232 soc_t& GetSoc() const { return GetSocFile()->GetSoc(); }
233};
234
235Q_DECLARE_METATYPE(SocRef)
236
204class SocDevRef : public SocRef 237class SocDevRef : public SocRef
205{ 238{
206public: 239public:
@@ -208,9 +241,9 @@ public:
208 SocDevRef(const SocRef& soc, int dev_idx, int dev_addr_idx) 241 SocDevRef(const SocRef& soc, int dev_idx, int dev_addr_idx)
209 :SocRef(soc), m_dev_idx(dev_idx), m_dev_addr_idx(dev_addr_idx) {} 242 :SocRef(soc), m_dev_idx(dev_idx), m_dev_addr_idx(dev_addr_idx) {}
210 int GetDevIndex() const { return m_dev_idx; } 243 int GetDevIndex() const { return m_dev_idx; }
211 const soc_dev_t& GetDev() const { return GetSoc().dev[GetDevIndex()]; } 244 soc_dev_t& GetDev() const { return GetSoc().dev[GetDevIndex()]; }
212 int GetDevAddrIndex() const { return m_dev_addr_idx; } 245 int GetDevAddrIndex() const { return m_dev_addr_idx; }
213 const soc_dev_addr_t& GetDevAddr() const { return GetDev().addr[GetDevAddrIndex()]; } 246 soc_dev_addr_t& GetDevAddr() const { return GetDev().addr[GetDevAddrIndex()]; }
214protected: 247protected:
215 int m_dev_idx, m_dev_addr_idx; 248 int m_dev_idx, m_dev_addr_idx;
216}; 249};
@@ -222,9 +255,9 @@ public:
222 SocRegRef(const SocDevRef& dev, int reg_idx, int reg_addr_idx) 255 SocRegRef(const SocDevRef& dev, int reg_idx, int reg_addr_idx)
223 :SocDevRef(dev), m_reg_idx(reg_idx), m_reg_addr_idx(reg_addr_idx) {} 256 :SocDevRef(dev), m_reg_idx(reg_idx), m_reg_addr_idx(reg_addr_idx) {}
224 int GetRegIndex() const { return m_reg_idx; } 257 int GetRegIndex() const { return m_reg_idx; }
225 const soc_reg_t& GetReg() const { return GetDev().reg[GetRegIndex()]; } 258 soc_reg_t& GetReg() const { return GetDev().reg[GetRegIndex()]; }
226 int GetRegAddrIndex() const { return m_reg_addr_idx; } 259 int GetRegAddrIndex() const { return m_reg_addr_idx; }
227 const soc_reg_addr_t& GetRegAddr() const { return GetReg().addr[GetRegAddrIndex()]; } 260 soc_reg_addr_t& GetRegAddr() const { return GetReg().addr[GetRegAddrIndex()]; }
228protected: 261protected:
229 int m_reg_idx, m_reg_addr_idx; 262 int m_reg_idx, m_reg_addr_idx;
230}; 263};
@@ -236,7 +269,7 @@ public:
236 SocFieldRef(const SocRegRef& reg, int field_idx) 269 SocFieldRef(const SocRegRef& reg, int field_idx)
237 :SocRegRef(reg), m_field_idx(field_idx) {} 270 :SocRegRef(reg), m_field_idx(field_idx) {}
238 int GetFieldIndex() const { return m_field_idx; } 271 int GetFieldIndex() const { return m_field_idx; }
239 const soc_reg_field_t& GetField() const { return GetReg().field[GetFieldIndex()]; } 272 soc_reg_field_t& GetField() const { return GetReg().field[GetFieldIndex()]; }
240protected: 273protected:
241 int m_field_idx; 274 int m_field_idx;
242}; 275};
@@ -247,9 +280,9 @@ class Backend : public QObject
247public: 280public:
248 Backend(); 281 Backend();
249 282
250 QStringList GetSocNameList(); 283 QList< SocFileRef > GetSocFileList();
284 QList< SocRef > GetSocList();
251 bool LoadSocDesc(const QString& filename); 285 bool LoadSocDesc(const QString& filename);
252 bool GetSocByName(const QString& name, SocRef& s);
253 IoBackend *CreateDummyIoBackend(); 286 IoBackend *CreateDummyIoBackend();
254 IoBackend *CreateFileIoBackend(const QString& filename); 287 IoBackend *CreateFileIoBackend(const QString& filename);
255#ifdef HAVE_HWSTUB 288#ifdef HAVE_HWSTUB
@@ -259,7 +292,7 @@ public:
259signals: 292signals:
260 void OnSocListChanged(); 293 void OnSocListChanged();
261private: 294private:
262 std::list< soc_t > m_socs; 295 std::list< SocFile > m_socs;
263}; 296};
264 297
265class BackendHelper 298class BackendHelper
diff --git a/utils/regtools/qeditor/mainwindow.cpp b/utils/regtools/qeditor/mainwindow.cpp
index 2ba781b042..cd0926851c 100644
--- a/utils/regtools/qeditor/mainwindow.cpp
+++ b/utils/regtools/qeditor/mainwindow.cpp
@@ -12,6 +12,7 @@
12 12
13#include "mainwindow.h" 13#include "mainwindow.h"
14#include "regtab.h" 14#include "regtab.h"
15#include "regedit.h"
15 16
16MyTabWidget::MyTabWidget() 17MyTabWidget::MyTabWidget()
17{ 18{
@@ -20,23 +21,37 @@ MyTabWidget::MyTabWidget()
20 connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(OnCloseTab(int))); 21 connect(this, SIGNAL(tabCloseRequested(int)), this, SLOT(OnCloseTab(int)));
21} 22}
22 23
23void MyTabWidget::OnCloseTab(int index) 24bool MyTabWidget::CloseTab(int index)
24{ 25{
25 QWidget *w = this->widget(index); 26 QWidget *w = this->widget(index);
26 removeTab(index); 27 DocumentTab *doc = dynamic_cast< DocumentTab* >(w);
27 delete w; 28 if(doc->Quit())
29 {
30 removeTab(index);
31 delete w;
32 return true;
33 }
34 else
35 return false;
36}
37
38void MyTabWidget::OnCloseTab(int index)
39{
40 CloseTab(index);
28} 41}
29 42
30MainWindow::MainWindow(Backend *backend) 43MainWindow::MainWindow(Backend *backend)
31 :m_backend(backend) 44 :m_backend(backend)
32{ 45{
33 QAction *new_regtab_act = new QAction(QIcon::fromTheme("document-new"), tr("&Register Tab"), this); 46 QAction *new_regtab_act = new QAction(QIcon::fromTheme("document-new"), tr("Register &Tab"), this);
47 QAction *new_regedit_act = new QAction(QIcon::fromTheme("document-edit"), tr("Register &Editor"), this);
34 QAction *load_desc_act = new QAction(QIcon::fromTheme("document-open"), tr("&Soc Description"), this); 48 QAction *load_desc_act = new QAction(QIcon::fromTheme("document-open"), tr("&Soc Description"), this);
35 QAction *quit_act = new QAction(QIcon::fromTheme("application-exit"), tr("&Quit"), this); 49 QAction *quit_act = new QAction(QIcon::fromTheme("application-exit"), tr("&Quit"), this);
36 QAction *about_act = new QAction(QIcon::fromTheme("help-about"), tr("&About"), this); 50 QAction *about_act = new QAction(QIcon::fromTheme("help-about"), tr("&About"), this);
37 QAction *about_qt_act = new QAction(QIcon::fromTheme("help-about"), tr("About &Qt"), this); 51 QAction *about_qt_act = new QAction(QIcon::fromTheme("help-about"), tr("About &Qt"), this);
38 52
39 connect(new_regtab_act, SIGNAL(triggered()), this, SLOT(OnNewRegTab())); 53 connect(new_regtab_act, SIGNAL(triggered()), this, SLOT(OnNewRegTab()));
54 connect(new_regedit_act, SIGNAL(triggered()), this, SLOT(OnNewRegEdit()));
40 connect(load_desc_act, SIGNAL(triggered()), this, SLOT(OnLoadDesc())); 55 connect(load_desc_act, SIGNAL(triggered()), this, SLOT(OnLoadDesc()));
41 connect(quit_act, SIGNAL(triggered()), this, SLOT(OnQuit())); 56 connect(quit_act, SIGNAL(triggered()), this, SLOT(OnQuit()));
42 connect(about_act, SIGNAL(triggered()), this, SLOT(OnAbout())); 57 connect(about_act, SIGNAL(triggered()), this, SLOT(OnAbout()));
@@ -48,6 +63,7 @@ MainWindow::MainWindow(Backend *backend)
48 file_menu->addAction(quit_act); 63 file_menu->addAction(quit_act);
49 64
50 new_submenu->addAction(new_regtab_act); 65 new_submenu->addAction(new_regtab_act);
66 new_submenu->addAction(new_regedit_act);
51 67
52 load_submenu->addAction(load_desc_act); 68 load_submenu->addAction(load_desc_act);
53 69
@@ -91,6 +107,8 @@ void MainWindow::OnAboutQt()
91 107
92void MainWindow::closeEvent(QCloseEvent *event) 108void MainWindow::closeEvent(QCloseEvent *event)
93{ 109{
110 if(!Quit())
111 return event->ignore();
94 WriteSettings(); 112 WriteSettings();
95 event->accept(); 113 event->accept();
96} 114}
@@ -100,7 +118,7 @@ void MainWindow::OnLoadDesc()
100 QFileDialog *fd = new QFileDialog(this); 118 QFileDialog *fd = new QFileDialog(this);
101 fd->setFilter("XML files (*.xml);;All files (*)"); 119 fd->setFilter("XML files (*.xml);;All files (*)");
102 fd->setFileMode(QFileDialog::ExistingFiles); 120 fd->setFileMode(QFileDialog::ExistingFiles);
103 fd->setDirectory(Settings::Get()->value("mainwindow/loaddescdir", QDir::currentPath()).toString()); 121 fd->setDirectory(Settings::Get()->value("loaddescdir", QDir::currentPath()).toString());
104 if(fd->exec()) 122 if(fd->exec())
105 { 123 {
106 QStringList filenames = fd->selectedFiles(); 124 QStringList filenames = fd->selectedFiles();
@@ -111,11 +129,42 @@ void MainWindow::OnLoadDesc()
111 msg.setText(QString("Cannot load ") + filenames[i]); 129 msg.setText(QString("Cannot load ") + filenames[i]);
112 msg.exec(); 130 msg.exec();
113 } 131 }
114 Settings::Get()->setValue("mainwindow/loaddescdir", fd->directory().absolutePath()); 132 Settings::Get()->setValue("loaddescdir", fd->directory().absolutePath());
115 } 133 }
116} 134}
117 135
136void MainWindow::OnTabModified(bool modified)
137{
138 QWidget *sender = qobject_cast< QWidget* >(QObject::sender());
139 int index = m_tab->indexOf(sender);
140 if(modified)
141 m_tab->setTabIcon(index, QIcon::fromTheme("document-save"));
142 else
143 m_tab->setTabIcon(index, QIcon());
144}
145
146void MainWindow::AddTab(QWidget *tab, const QString& title)
147{
148 connect(tab, SIGNAL(OnModified(bool)), this, SLOT(OnTabModified(bool)));
149 m_tab->setCurrentIndex(m_tab->addTab(tab, title));
150}
151
118void MainWindow::OnNewRegTab() 152void MainWindow::OnNewRegTab()
119{ 153{
120 m_tab->addTab(new RegTab(m_backend), "Register Tab"); 154 AddTab(new RegTab(m_backend, this), "Register Tab");
155}
156
157void MainWindow::OnNewRegEdit()
158{
159 AddTab(new RegEdit(m_backend, this), "Register Editor");
160}
161
162bool MainWindow::Quit()
163{
164 while(m_tab->count() > 0)
165 {
166 if(!m_tab->CloseTab(0))
167 return false;
168 }
169 return true;
121} 170}
diff --git a/utils/regtools/qeditor/mainwindow.h b/utils/regtools/qeditor/mainwindow.h
index d7dab3717f..b32b0647f5 100644
--- a/utils/regtools/qeditor/mainwindow.h
+++ b/utils/regtools/qeditor/mainwindow.h
@@ -7,11 +7,19 @@
7#include "backend.h" 7#include "backend.h"
8#include "settings.h" 8#include "settings.h"
9 9
10class DocumentTab
11{
12public:
13 virtual bool Quit() = 0;
14 virtual void OnModified(bool modified) = 0;
15};
16
10class MyTabWidget : public QTabWidget 17class MyTabWidget : public QTabWidget
11{ 18{
12 Q_OBJECT 19 Q_OBJECT
13public: 20public:
14 MyTabWidget(); 21 MyTabWidget();
22 bool CloseTab(int index);
15 23
16private slots: 24private slots:
17 void OnCloseTab(int index); 25 void OnCloseTab(int index);
@@ -30,15 +38,21 @@ public:
30private: 38private:
31 void closeEvent(QCloseEvent *event); 39 void closeEvent(QCloseEvent *event);
32 40
41protected:
42 void AddTab(QWidget *tab, const QString& title);
43 bool Quit();
44
33private slots: 45private slots:
34 void OnQuit(); 46 void OnQuit();
35 void OnAbout(); 47 void OnAbout();
36 void OnAboutQt(); 48 void OnAboutQt();
37 void OnLoadDesc(); 49 void OnLoadDesc();
38 void OnNewRegTab(); 50 void OnNewRegTab();
51 void OnNewRegEdit();
52 void OnTabModified(bool modified);
39 53
40private: 54private:
41 QTabWidget *m_tab; 55 MyTabWidget *m_tab;
42 Backend *m_backend; 56 Backend *m_backend;
43}; 57};
44 58
diff --git a/utils/regtools/qeditor/qeditor.pro b/utils/regtools/qeditor/qeditor.pro
index 5604fe9d41..38d7c987bf 100644
--- a/utils/regtools/qeditor/qeditor.pro
+++ b/utils/regtools/qeditor/qeditor.pro
@@ -1,7 +1,9 @@
1QT += widgets 1QT += widgets
2 2
3HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h std_analysers.h 3HEADERS += mainwindow.h backend.h regtab.h analyser.h settings.h \
4SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp std_analysers.cpp settings.cpp 4 std_analysers.h aux.h regdisplaypanel.h regedit.h
5SOURCES += main.cpp mainwindow.cpp regtab.cpp backend.cpp analyser.cpp \
6 std_analysers.cpp settings.cpp aux.cpp regdisplaypanel.cpp regedit.cpp
5LIBS += -L../lib/ -lsocdesc -lxml2 7LIBS += -L../lib/ -lsocdesc -lxml2
6INCLUDEPATH += ../lib/ ../../hwstub/lib 8INCLUDEPATH += ../lib/ ../../hwstub/lib
7 9
diff --git a/utils/regtools/qeditor/regdisplaypanel.cpp b/utils/regtools/qeditor/regdisplaypanel.cpp
new file mode 100644
index 0000000000..cef5f9807b
--- /dev/null
+++ b/utils/regtools/qeditor/regdisplaypanel.cpp
@@ -0,0 +1,314 @@
1#include "regdisplaypanel.h"
2#include <QHeaderView>
3#include <QDebug>
4
5/**
6 * RegItemEditorCreator
7 */
8
9QWidget *RegItemEditorCreator::createWidget(QWidget * parent) const
10{
11 return new RegLineEdit(parent);
12}
13
14QByteArray RegItemEditorCreator::valuePropertyName () const
15{
16 return QByteArray("text");
17}
18
19/**
20 * DevDisplayPanel
21 */
22DevDisplayPanel::DevDisplayPanel(QWidget *parent, const SocDevRef& dev_ref)
23 :QGroupBox(parent), m_dev(dev_ref), m_reg_font(font())
24{
25 QVBoxLayout *right_layout = new QVBoxLayout;
26 const soc_dev_addr_t& dev_addr = m_dev.GetDevAddr();
27
28 m_reg_font.setWeight(100);
29 m_reg_font.setKerning(false);
30
31 QString dev_name;
32 dev_name.sprintf("HW_%s_BASE", dev_addr.name.c_str());
33
34 QLabel *label_names = new QLabel("<b>" + dev_name + "</b>");
35 label_names->setTextFormat(Qt::RichText);
36
37 QLabel *label_addr = new QLabel("<b>" + QString().sprintf("0x%03x", dev_addr.addr) + "</b>");
38 label_addr->setTextFormat(Qt::RichText);
39
40 QHBoxLayout *top_layout = new QHBoxLayout;
41 top_layout->addStretch();
42 top_layout->addWidget(label_names);
43 top_layout->addWidget(label_addr);
44 top_layout->addStretch();
45
46 m_name = new QLabel(this);
47 m_name->setTextFormat(Qt::RichText);
48 m_name->setText("<h1>" + QString::fromStdString(m_dev.GetDev().long_name) + "</h1>");
49
50 m_desc = new QLabel(this);
51 m_name->setTextFormat(Qt::RichText);
52 m_desc->setText(QString::fromStdString(m_dev.GetDev().desc));
53
54 right_layout->addLayout(top_layout, 0);
55 right_layout->addWidget(m_name, 0);
56 right_layout->addWidget(m_desc, 0);
57 right_layout->addStretch(1);
58
59 setTitle("Device Description");
60 setLayout(right_layout);
61}
62
63void DevDisplayPanel::AllowWrite(bool en)
64{
65 Q_UNUSED(en);
66}
67
68QWidget *DevDisplayPanel::GetWidget()
69{
70 return this;
71}
72
73/**
74 * RegDisplayPanel
75 */
76
77RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg_ref)
78 :QGroupBox(parent), m_io_backend(io_backend), m_reg(reg_ref), m_reg_font(font())
79{
80 bool read_only = m_io_backend->IsReadOnly();
81
82 QVBoxLayout *right_layout = new QVBoxLayout;
83
84 const soc_dev_addr_t& dev_addr = m_reg.GetDevAddr();
85 const soc_reg_t& reg = m_reg.GetReg();
86 const soc_reg_addr_t& reg_addr = m_reg.GetRegAddr();
87
88 m_reg_font.setWeight(100);
89 m_reg_font.setKerning(false);
90
91 QString reg_name;
92 reg_name.sprintf("HW_%s_%s", dev_addr.name.c_str(), reg_addr.name.c_str());
93 QStringList names;
94 QVector< soc_addr_t > addresses;
95 names.append(reg_name);
96 addresses.append(reg_addr.addr);
97 if(reg.flags & REG_HAS_SCT)
98 {
99 names.append(reg_name + "_SET");
100 names.append(reg_name + "_CLR");
101 names.append(reg_name + "_TOG");
102 addresses.append(reg_addr.addr + 4);
103 addresses.append(reg_addr.addr + 8);
104 addresses.append(reg_addr.addr + 12);
105 }
106
107 QString str;
108 str += "<table align=left>";
109 for(int i = 0; i < names.size(); i++)
110 str += "<tr><td><b>" + names[i] + "</b></td></tr>";
111 str += "</table>";
112 QLabel *label_names = new QLabel;
113 label_names->setTextFormat(Qt::RichText);
114 label_names->setText(str);
115
116 QString str_addr;
117 str_addr += "<table align=left>";
118 for(int i = 0; i < names.size(); i++)
119 str_addr += "<tr><td><b>" + QString().sprintf("0x%03x", addresses[i]) + "</b></td></tr>";
120 str_addr += "</table>";
121 QLabel *label_addr = new QLabel;
122 label_addr->setTextFormat(Qt::RichText);
123 label_addr->setText(str_addr);
124
125 QHBoxLayout *top_layout = new QHBoxLayout;
126 top_layout->addStretch();
127 top_layout->addWidget(label_names);
128 top_layout->addWidget(label_addr);
129 top_layout->addStretch();
130
131 m_raw_val_name = new QLabel;
132 m_raw_val_name->setText("Raw value:");
133 m_raw_val_edit = new RegLineEdit;
134 m_raw_val_edit->SetReadOnly(read_only);
135 m_raw_val_edit->GetLineEdit()->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
136 m_raw_val_edit->GetLineEdit()->setValidator(new SocFieldValidator(m_raw_val_edit));
137 m_raw_val_edit->EnableSCT(!!(reg.flags & REG_HAS_SCT));
138 m_raw_val_edit->GetLineEdit()->setFont(m_reg_font);
139 connect(m_raw_val_edit->GetLineEdit(), SIGNAL(returnPressed()), this, SLOT(OnRawRegValueReturnPressed()));
140 QHBoxLayout *raw_val_layout = new QHBoxLayout;
141 raw_val_layout->addStretch();
142 raw_val_layout->addWidget(m_raw_val_name);
143 raw_val_layout->addWidget(m_raw_val_edit);
144 raw_val_layout->addStretch();
145
146 m_value_table = new GrowingTableWidget;
147 m_value_table->setRowCount(reg.field.size());
148 m_value_table->setColumnCount(5);
149 for(size_t row = 0; row < reg.field.size(); row++)
150 {
151 const soc_reg_field_t& field = reg.field[row];
152 QString bits_str;
153 if(field.first_bit == field.last_bit)
154 bits_str.sprintf("%d", field.first_bit);
155 else
156 bits_str.sprintf("%d:%d", field.last_bit, field.first_bit);
157 QTableWidgetItem *item = new QTableWidgetItem(bits_str);
158 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
159 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
160 m_value_table->setItem(row, 0, item);
161 item = new QTableWidgetItem(QString(field.name.c_str()));
162 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
163 m_value_table->setItem(row, 1, item);
164 item = new QTableWidgetItem(QString(field.desc.c_str()));
165 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
166 m_value_table->setItem(row, 4, item);
167 }
168 m_value_table->setHorizontalHeaderItem(0, new QTableWidgetItem("Bits"));
169 m_value_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name"));
170 m_value_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Value"));
171 m_value_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Meaning"));
172 m_value_table->setHorizontalHeaderItem(4, new QTableWidgetItem("Description"));
173 m_value_table->verticalHeader()->setVisible(false);
174 m_value_table->resizeColumnsToContents();
175 m_value_table->horizontalHeader()->setStretchLastSection(true);
176 m_value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
177
178 m_table_delegate = new QStyledItemDelegate(this);
179 m_table_edit_factory = new QItemEditorFactory();
180 m_regedit_creator = new RegItemEditorCreator();
181 m_table_edit_factory->registerEditor(QVariant::String, m_regedit_creator);
182 m_table_delegate->setItemEditorFactory(m_table_edit_factory);
183 m_value_table->setItemDelegate(m_table_delegate);
184
185 m_sexy_display = new RegSexyDisplay(reg_ref, this);
186 m_sexy_display->setFont(m_reg_font);
187
188 m_desc = new QLabel(this);
189 m_desc->setTextFormat(Qt::RichText);
190 m_desc->setText(QString::fromStdString(m_reg.GetReg().desc));
191
192 right_layout->addWidget(m_desc);
193 right_layout->addLayout(top_layout);
194 if(raw_val_layout)
195 right_layout->addLayout(raw_val_layout);
196 right_layout->addWidget(m_sexy_display);
197 right_layout->addWidget(m_value_table);
198
199 setTitle("Register Description");
200 m_viewport = new QWidget;
201 m_viewport->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
202 m_viewport->setLayout(right_layout);
203 m_scroll = new QScrollArea;
204 m_scroll->setWidget(m_viewport);
205 m_scroll->setWidgetResizable(true);
206 m_scroll->setFrameShape(QFrame::NoFrame);
207 QHBoxLayout *layout = new QHBoxLayout;
208 layout->addWidget(m_scroll, 1);
209 setLayout(layout);
210 AllowWrite(false);
211
212 // load data
213 Reload();
214}
215
216RegDisplayPanel::~RegDisplayPanel()
217{
218 delete m_table_edit_factory;
219}
220
221void RegDisplayPanel::Reload()
222{
223 const soc_dev_addr_t& dev_addr = m_reg.GetDevAddr();
224 const soc_reg_t& reg = m_reg.GetReg();
225 const soc_reg_addr_t& reg_addr = m_reg.GetRegAddr();
226 soc_word_t value;
227 BackendHelper helper(m_io_backend, m_reg);
228 bool has_value = helper.ReadRegister(dev_addr.name.c_str(), reg_addr.name.c_str(), value);
229
230 if(has_value)
231 {
232 m_raw_val_name->show();
233 m_raw_val_edit->show();
234 m_raw_val_edit->GetLineEdit()->setText(QString().sprintf("0x%08x", value));
235 }
236 else
237 {
238 m_raw_val_name->hide();
239 m_raw_val_edit->hide();
240 }
241
242 int row = 0;
243 foreach(const soc_reg_field_t& field, reg.field)
244 {
245 QTableWidgetItem *item = new QTableWidgetItem();
246 QTableWidgetItem *desc_item = new QTableWidgetItem();
247 if(has_value)
248 {
249 soc_word_t v = (value & field.bitmask()) >> field.first_bit;
250 QString value_name;
251 foreach(const soc_reg_field_value_t& rval, field.value)
252 if(v == rval.value)
253 value_name = rval.name.c_str();
254 const char *fmt = "%lu";
255 // heuristic
256 if((field.last_bit - field.first_bit + 1) > 16)
257 fmt = "0x%lx";
258 item->setText(QString().sprintf(fmt, (unsigned long)v));
259 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
260
261 if(value_name.size() != 0)
262 {
263 desc_item->setText(value_name);
264 desc_item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
265 }
266 }
267 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
268 desc_item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
269 m_value_table->setItem(row, 2, item);
270 m_value_table->setItem(row, 3, desc_item);
271 row++;
272 }
273}
274
275void RegDisplayPanel::AllowWrite(bool en)
276{
277 m_allow_write = en;
278 if(m_raw_val_edit)
279 m_raw_val_edit->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write);
280}
281
282IoBackend::WriteMode RegDisplayPanel::EditModeToWriteMode(RegLineEdit::EditMode mode)
283{
284 switch(mode)
285 {
286 case RegLineEdit::Write: return IoBackend::Write;
287 case RegLineEdit::Set: return IoBackend::Set;
288 case RegLineEdit::Clear: return IoBackend::Clear;
289 case RegLineEdit::Toggle: return IoBackend::Toggle;
290 default: return IoBackend::Write;
291 }
292}
293
294void RegDisplayPanel::OnRawRegValueReturnPressed()
295{
296 soc_word_t val;
297 QLineEdit *edit = m_raw_val_edit->GetLineEdit();
298 const SocFieldValidator *validator = dynamic_cast< const SocFieldValidator *>(edit->validator());
299 QValidator::State state = validator->parse(edit->text(), val);
300 if(state != QValidator::Acceptable)
301 return;
302 IoBackend::WriteMode mode = EditModeToWriteMode(m_raw_val_edit->GetMode());
303 BackendHelper helper(m_io_backend, m_reg);
304 helper.WriteRegister(m_reg.GetDevAddr().name.c_str(), m_reg.GetRegAddr().name.c_str(),
305 val, mode);
306 // FIXME: we should notify the UI to read value back because it has changed
307 Reload();
308}
309
310QWidget *RegDisplayPanel::GetWidget()
311{
312 return this;
313}
314
diff --git a/utils/regtools/qeditor/regdisplaypanel.h b/utils/regtools/qeditor/regdisplaypanel.h
new file mode 100644
index 0000000000..444f3615f2
--- /dev/null
+++ b/utils/regtools/qeditor/regdisplaypanel.h
@@ -0,0 +1,77 @@
1#ifndef REGDISPLAYPANEL_H
2#define REGDISPLAYPANEL_H
3
4#include <QVBoxLayout>
5#include <QLabel>
6#include <QGroupBox>
7#include <QTableWidget>
8#include <QStyledItemDelegate>
9#include <QItemEditorCreatorBase>
10#include <QTextEdit>
11#include <QScrollArea>
12#include <soc_desc.hpp>
13#include "backend.h"
14#include "settings.h"
15#include "aux.h"
16#include "regtab.h"
17
18class RegItemEditorCreator : public QItemEditorCreatorBase
19{
20public:
21 RegItemEditorCreator() {}
22 virtual QWidget *createWidget(QWidget * parent) const;
23 virtual QByteArray valuePropertyName () const;
24};
25
26class DevDisplayPanel : public QGroupBox, public RegTabPanel
27{
28 Q_OBJECT
29public:
30 DevDisplayPanel(QWidget *parent, const SocDevRef& reg);
31 void Reload();
32 void AllowWrite(bool en);
33 QWidget *GetWidget();
34 bool Quit();
35
36protected:
37
38 const SocDevRef& m_dev;
39 QFont m_reg_font;
40 QLabel *m_name;
41 QLabel *m_desc;
42};
43
44class RegDisplayPanel : public QGroupBox, public RegTabPanel
45{
46 Q_OBJECT
47public:
48 RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg);
49 ~RegDisplayPanel();
50 void AllowWrite(bool en);
51 void Reload();
52 QWidget *GetWidget();
53 bool Quit();
54
55protected:
56 IoBackend::WriteMode EditModeToWriteMode(RegLineEdit::EditMode mode);
57
58 IoBackend *m_io_backend;
59 const SocRegRef& m_reg;
60 bool m_allow_write;
61 RegLineEdit *m_raw_val_edit;
62 RegSexyDisplay *m_sexy_display;
63 GrowingTableWidget *m_value_table;
64 QStyledItemDelegate *m_table_delegate;
65 QItemEditorFactory *m_table_edit_factory;
66 RegItemEditorCreator *m_regedit_creator;
67 QLabel *m_raw_val_name;
68 QFont m_reg_font;
69 QLabel *m_desc;
70 QWidget *m_viewport;
71 QScrollArea *m_scroll;
72
73private slots:
74 void OnRawRegValueReturnPressed();
75};
76
77#endif /* REGDISPLAYPANEL_H */
diff --git a/utils/regtools/qeditor/regedit.cpp b/utils/regtools/qeditor/regedit.cpp
new file mode 100644
index 0000000000..5e498ce496
--- /dev/null
+++ b/utils/regtools/qeditor/regedit.cpp
@@ -0,0 +1,1324 @@
1#include "regedit.h"
2#include <QFileDialog>
3#include <QDebug>
4#include <QHeaderView>
5#include <QMessageBox>
6#include <QInputDialog>
7
8/**
9 * EmptyEditPanel
10 */
11EmptyEditPanel::EmptyEditPanel(QWidget *parent)
12 :QWidget(parent)
13{
14}
15
16/**
17 * SocEditPanel
18 */
19SocEditPanel::SocEditPanel(SocRef ref, QWidget *parent)
20 :QWidget(parent), m_ref(ref)
21{
22 m_name_group = new QGroupBox("Name", this);
23 m_name_edit = new QLineEdit(this);
24 m_name_edit->setText(QString::fromStdString(ref.GetSoc().name));
25 QVBoxLayout *name_group_layout = new QVBoxLayout;
26 name_group_layout->addWidget(m_name_edit);
27 m_name_group->setLayout(name_group_layout);
28
29 m_desc_group = new QGroupBox("Description", this);
30 QHBoxLayout *group_layout = new QHBoxLayout;
31 m_desc_edit = new MyTextEditor(this);
32 m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetSoc().desc));
33 group_layout->addWidget(m_desc_edit);
34 m_desc_group->setLayout(group_layout);
35
36 QVBoxLayout *layout = new QVBoxLayout;
37 layout->addWidget(m_name_group);
38 layout->addWidget(m_desc_group);
39 layout->addStretch(1);
40
41 connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&)));
42 connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnTextEdited()));
43
44 setLayout(layout);
45}
46
47void SocEditPanel::OnNameEdited(const QString& text)
48{
49 m_ref.GetSoc().name = text.toStdString();
50 emit OnModified(m_name_edit->isModified());
51}
52
53void SocEditPanel::OnTextEdited()
54{
55 m_ref.GetSoc().desc = m_desc_edit->GetTextHtml().toStdString();
56 emit OnModified(m_desc_edit->IsModified());
57}
58
59/**
60 * DevEditPanel
61 */
62DevEditPanel::DevEditPanel(SocDevRef ref, QWidget *parent)
63 :QWidget(parent), m_ref(ref)
64{
65 m_name_group = new QGroupBox("Name", this);
66 m_name_edit = new QLineEdit(this);
67 m_name_edit->setText(QString::fromStdString(ref.GetDev().name));
68 QVBoxLayout *name_group_layout = new QVBoxLayout;
69 name_group_layout->addWidget(m_name_edit);
70 m_name_group->setLayout(name_group_layout);
71
72 m_long_name_group = new QGroupBox("Long Name", this);
73 m_long_name_edit = new QLineEdit(this);
74 m_long_name_edit->setText(QString::fromStdString(ref.GetDev().long_name));
75 QVBoxLayout *long_name_group_layout = new QVBoxLayout;
76 long_name_group_layout->addWidget(m_long_name_edit);
77 m_long_name_group->setLayout(long_name_group_layout);
78
79 m_version_group = new QGroupBox("Version", this);
80 m_version_edit = new QLineEdit(this);
81 m_version_edit->setText(QString::fromStdString(ref.GetDev().version));
82 QVBoxLayout *version_group_layout = new QVBoxLayout;
83 version_group_layout->addWidget(m_version_edit);
84 m_version_group->setLayout(version_group_layout);
85
86 QVBoxLayout *name_ver_layout = new QVBoxLayout;
87 name_ver_layout->addWidget(m_name_group);
88 name_ver_layout->addWidget(m_long_name_group);
89 name_ver_layout->addWidget(m_version_group);
90 name_ver_layout->addStretch();
91
92 m_instances_table = new QTableWidget(this);
93 m_instances_table->setRowCount(ref.GetDev().addr.size() + 1);
94 m_instances_table->setColumnCount(3);
95 for(size_t row = 0; row < ref.GetDev().addr.size(); row++)
96 FillRow(row, ref.GetDev().addr[row]);
97 CreateNewRow(ref.GetDev().addr.size());
98 m_instances_table->setHorizontalHeaderItem(0, new QTableWidgetItem(""));
99 m_instances_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name"));
100 m_instances_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Address"));
101 m_instances_table->verticalHeader()->setVisible(false);
102 m_instances_table->resizeColumnsToContents();
103 m_instances_table->horizontalHeader()->setStretchLastSection(true);
104 m_instances_table->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
105 m_instances_group = new QGroupBox("Instances", this);
106 QHBoxLayout *instances_group_layout = new QHBoxLayout;
107 instances_group_layout->addWidget(m_instances_table);
108 m_instances_group->setLayout(instances_group_layout);
109
110 QHBoxLayout *top_layout = new QHBoxLayout;
111 top_layout->addWidget(m_instances_group);
112 top_layout->addLayout(name_ver_layout);
113 top_layout->addStretch();
114
115 m_desc_group = new QGroupBox("Description", this);
116 QHBoxLayout *group_layout = new QHBoxLayout;
117 m_desc_edit = new MyTextEditor(this);
118 m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetDev().desc));
119 group_layout->addWidget(m_desc_edit);
120 m_desc_group->setLayout(group_layout);
121
122 QVBoxLayout *layout = new QVBoxLayout;
123 layout->addLayout(top_layout, 0);
124 layout->addWidget(m_desc_group, 1);
125
126 setLayout(layout);
127
128 SocFieldItemDelegate *m_table_delegate = new SocFieldItemDelegate(this);
129 QItemEditorFactory *m_table_edit_factory = new QItemEditorFactory();
130 SocFieldEditorCreator *m_table_edit_creator = new SocFieldEditorCreator();
131 m_table_edit_factory->registerEditor(QVariant::UInt, m_table_edit_creator);
132 m_table_delegate->setItemEditorFactory(m_table_edit_factory);
133 m_instances_table->setItemDelegate(m_table_delegate);
134
135 connect(m_instances_table, SIGNAL(cellActivated(int,int)), this, SLOT(OnInstActivated(int,int)));
136 connect(m_instances_table, SIGNAL(cellChanged(int,int)), this, SLOT(OnInstChanged(int,int)));
137 connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&)));
138 connect(m_long_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnLongNameEdited(const QString&)));
139 connect(m_version_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnVersionEdited(const QString&)));
140 connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited()));
141}
142
143void DevEditPanel::OnNameEdited(const QString& text)
144{
145 m_ref.GetDev().name = text.toStdString();
146 emit OnModified(m_name_edit->isModified());
147}
148
149void DevEditPanel::OnLongNameEdited(const QString& text)
150{
151 m_ref.GetDev().long_name = text.toStdString();
152 emit OnModified(m_long_name_edit->isModified());
153}
154
155void DevEditPanel::OnVersionEdited(const QString& text)
156{
157 m_ref.GetDev().version = text.toStdString();
158 emit OnModified(m_version_edit->isModified());
159}
160
161void DevEditPanel::OnDescEdited()
162{
163 m_ref.GetDev().desc = m_desc_edit->GetTextHtml().toStdString();
164 emit OnModified(m_desc_edit->IsModified());
165}
166
167void DevEditPanel::CreateNewRow(int row)
168{
169 QTableWidgetItem *item = new QTableWidgetItem(QIcon::fromTheme("list-add"), "", DevInstNewType);
170 item->setToolTip("New?");
171 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
172 m_instances_table->setItem(row, DevInstIconColumn, item);
173 item = new QTableWidgetItem("New instance...");
174 QFont font = item->font();
175 font.setItalic(true);
176 item->setFont(font);
177 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
178 m_instances_table->setItem(row, DevInstNameColumn, item);
179 item = new QTableWidgetItem("");
180 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
181 m_instances_table->setItem(row, DevInstAddrColumn, item);
182}
183
184void DevEditPanel::FillRow(int row, const soc_dev_addr_t& addr)
185{
186 QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(addr.name));
187 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
188 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
189 m_instances_table->setItem(row, DevInstNameColumn, item);
190 item = new QTableWidgetItem();
191 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
192 item->setData(Qt::DisplayRole, QVariant(addr.addr));
193 m_instances_table->setItem(row, DevInstAddrColumn, item);
194 item = new QTableWidgetItem(QIcon::fromTheme("list-remove"), "", DevInstDeleteType);
195 item->setToolTip("Remove?");
196 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
197 m_instances_table->setItem(row, DevInstIconColumn, item);
198}
199
200void DevEditPanel::OnInstActivated(int row, int column)
201{
202 if(column != 0)
203 return;
204 int type = m_instances_table->item(row, column)->type();
205 if(type == DevInstDeleteType)
206 {
207 m_ref.GetDev().addr.erase(m_ref.GetDev().addr.begin() + row);
208 m_instances_table->removeRow(row);
209 }
210 else if(type == DevInstNewType)
211 {
212 m_instances_table->insertRow(row);
213 soc_dev_addr_t addr;
214 addr.name = QString("UNNAMED_%1").arg(row).toStdString();
215 addr.addr = 0;
216 m_ref.GetDev().addr.push_back(addr);
217 FillRow(row, addr);
218 }
219}
220
221void DevEditPanel::OnInstChanged(int row, int column)
222{
223 /* ignore extra row for addition */
224 if(row >= (int)m_ref.GetDev().addr.size())
225 return;
226 QTableWidgetItem *item = m_instances_table->item(row, column);
227 if(column == DevInstNameColumn)
228 {
229 m_ref.GetDev().addr[row].name = item->text().toStdString();
230 emit OnModified(true);
231 }
232 else if(column == DevInstAddrColumn)
233 {
234 m_ref.GetDev().addr[row].addr = item->data(Qt::DisplayRole).toUInt();
235 emit OnModified(true);
236 }
237}
238
239/**
240 * RegEditPanel
241 */
242
243RegEditPanel::RegEditPanel(SocRegRef ref, QWidget *parent)
244 :QWidget(parent), m_ref(ref), m_reg_font(font())
245{
246 m_reg_font.setWeight(100);
247 m_reg_font.setKerning(false);
248
249 m_name_group = new QGroupBox("Name", this);
250 m_name_edit = new QLineEdit(this);
251 m_name_edit->setText(QString::fromStdString(ref.GetReg().name));
252 QVBoxLayout *name_group_layout = new QVBoxLayout;
253 name_group_layout->addWidget(m_name_edit);
254 m_name_group->setLayout(name_group_layout);
255
256 m_instances_table = new QTableWidget(this);
257 m_instances_table->setRowCount(ref.GetReg().addr.size() + 1);
258 m_instances_table->setColumnCount(RegInstNrColumns);
259 for(size_t row = 0; row < ref.GetReg().addr.size(); row++)
260 FillRow(row, ref.GetReg().addr[row]);
261 CreateNewAddrRow(ref.GetReg().addr.size());
262 m_instances_table->setHorizontalHeaderItem(RegInstIconColumn, new QTableWidgetItem(""));
263 m_instances_table->setHorizontalHeaderItem(RegInstNameColumn, new QTableWidgetItem("Name"));
264 m_instances_table->setHorizontalHeaderItem(RegInstAddrColumn, new QTableWidgetItem("Address"));
265 m_instances_table->verticalHeader()->setVisible(false);
266 m_instances_table->resizeColumnsToContents();
267 m_instances_table->horizontalHeader()->setStretchLastSection(true);
268 m_instances_table->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
269 m_instances_group = new QGroupBox("Instances", this);
270 QHBoxLayout *instances_group_layout = new QHBoxLayout;
271 instances_group_layout->addWidget(m_instances_table);
272 m_instances_group->setLayout(instances_group_layout);
273
274 m_desc_group = new QGroupBox("Description", this);
275 QHBoxLayout *group_layout = new QHBoxLayout;
276 m_desc_edit = new MyTextEditor(this);
277 m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetReg().desc));
278 group_layout->addWidget(m_desc_edit);
279 m_desc_group->setLayout(group_layout);
280
281 bool has_sct = m_ref.GetReg().flags & REG_HAS_SCT;
282 m_sct_check = new QCheckBox("Set/Clear/Toggle", this);
283 m_sct_check->setCheckState(has_sct ? Qt::Checked : Qt::Unchecked);
284 QHBoxLayout *flags_layout = new QHBoxLayout;
285 flags_layout->addWidget(m_sct_check);
286 flags_layout->addStretch();
287 m_flags_group = new QGroupBox("Flags", this);
288 m_flags_group->setLayout(flags_layout);
289
290 m_formula_combo = new QComboBox(this);
291 m_formula_combo->addItem("None", QVariant(REG_FORMULA_NONE));
292 m_formula_combo->addItem("String", QVariant(REG_FORMULA_STRING));
293 m_formula_combo->setCurrentIndex(m_formula_combo->findData(QVariant(m_ref.GetReg().formula.type)));
294 m_formula_type_label = new QLabel("Type:", this);
295 QHBoxLayout *formula_top_layout = new QHBoxLayout;
296 formula_top_layout->addWidget(m_formula_type_label);
297 formula_top_layout->addWidget(m_formula_combo);
298 m_formula_string_edit = new QLineEdit(QString::fromStdString(ref.GetReg().formula.string), this);
299 QVBoxLayout *formula_layout = new QVBoxLayout;
300 formula_layout->addLayout(formula_top_layout);
301 formula_layout->addWidget(m_formula_string_edit);
302 m_formula_string_gen = new QPushButton("Generate", this);
303 formula_layout->addWidget(m_formula_string_gen);
304 m_formula_group = new QGroupBox("Formula", this);
305 m_formula_group->setLayout(formula_layout);
306
307 QVBoxLayout *name_layout = new QVBoxLayout;
308 name_layout->addWidget(m_name_group);
309 name_layout->addWidget(m_flags_group);
310 name_layout->addWidget(m_formula_group);
311 name_layout->addStretch();
312
313 QHBoxLayout *top_layout = new QHBoxLayout;
314 top_layout->addWidget(m_instances_group);
315 top_layout->addLayout(name_layout);
316 top_layout->addWidget(m_desc_group, 1);
317
318 m_sexy_display = new RegSexyDisplay(m_ref, this);
319 m_sexy_display->setFont(m_reg_font);
320
321 m_field_table = new QTableWidget;
322 m_field_table->setRowCount(m_ref.GetReg().field.size());
323 m_field_table->setColumnCount(4);
324 for(size_t row = 0; row < m_ref.GetReg().field.size(); row++)
325 {
326 const soc_reg_field_t& field = m_ref.GetReg().field[row];
327 QString bits_str;
328 if(field.first_bit == field.last_bit)
329 bits_str.sprintf("%d", field.first_bit);
330 else
331 bits_str.sprintf("%d:%d", field.last_bit, field.first_bit);
332 QTableWidgetItem *item = new QTableWidgetItem(bits_str);
333 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
334 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
335 m_field_table->setItem(row, 1, item);
336 item = new QTableWidgetItem(QString(field.name.c_str()));
337 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
338 m_field_table->setItem(row, 2, item);
339 item = new QTableWidgetItem(QString(field.desc.c_str()));
340 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
341 m_field_table->setItem(row, 3, item);
342 UpdateWarning(row);
343 }
344 m_field_table->setHorizontalHeaderItem(0, new QTableWidgetItem(""));
345 m_field_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Bits"));
346 m_field_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Name"));
347 m_field_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Description"));
348 m_field_table->verticalHeader()->setVisible(false);
349 m_field_table->resizeColumnsToContents();
350 m_field_table->horizontalHeader()->setStretchLastSection(true);
351 QHBoxLayout *field_layout = new QHBoxLayout;
352 field_layout->addWidget(m_field_table);
353 m_field_group = new QGroupBox("Flags", this);
354 m_field_group->setLayout(field_layout);
355
356 QVBoxLayout *layout = new QVBoxLayout;
357 layout->addLayout(top_layout, 0);
358 layout->addWidget(m_sexy_display, 0);
359 layout->addWidget(m_field_group);
360
361 UpdateFormula();
362
363 setLayout(layout);
364
365 SocFieldItemDelegate *m_table_delegate = new SocFieldItemDelegate(this);
366 QItemEditorFactory *m_table_edit_factory = new QItemEditorFactory();
367 SocFieldEditorCreator *m_table_edit_creator = new SocFieldEditorCreator();
368 m_table_edit_factory->registerEditor(QVariant::UInt, m_table_edit_creator);
369 m_table_delegate->setItemEditorFactory(m_table_edit_factory);
370 m_instances_table->setItemDelegate(m_table_delegate);
371
372 connect(m_instances_table, SIGNAL(cellActivated(int,int)), this, SLOT(OnInstActivated(int,int)));
373 connect(m_instances_table, SIGNAL(cellChanged(int,int)), this, SLOT(OnInstChanged(int,int)));
374 connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&)));
375 connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited()));
376 connect(m_sct_check, SIGNAL(stateChanged(int)), this, SLOT(OnSctEdited(int)));
377 connect(m_formula_combo, SIGNAL(currentIndexChanged(int)), this, SLOT(OnFormulaChanged(int)));
378 connect(m_formula_string_edit, SIGNAL(textChanged(const QString&)), this,
379 SLOT(OnFormulaStringChanged(const QString&)));
380 connect(m_formula_string_gen, SIGNAL(clicked(bool)), this, SLOT(OnFormulaGenerate(bool)));
381}
382
383void RegEditPanel::UpdateWarning(int row)
384{
385 Q_UNUSED(row);
386}
387
388void RegEditPanel::OnFormulaStringChanged(const QString& text)
389{
390 m_ref.GetReg().formula.string = text.toStdString();
391 emit OnModified(true);
392}
393
394void RegEditPanel::OnFormulaGenerate(bool checked)
395{
396 Q_UNUSED(checked);
397 bool ok;
398 int count = QInputDialog::getInt(this, "Instance generator", "Number of instances",
399 0, 0, 100, 1, &ok);
400 if(!ok)
401 return;
402 std::string name(m_ref.GetReg().name);
403 size_t pos = name.find('n');
404 if(pos == std::string::npos)
405 {
406 name.push_back('n');
407 pos = name.size() - 1;
408 }
409 std::map< std::string, soc_word_t > map;
410 std::vector< std::pair< std::string, soc_word_t > > list;
411 std::string formula = m_ref.GetReg().formula.string;
412 for(int n = 0; n < count; n++)
413 {
414 map["n"] = n;
415 std::string err;
416 soc_word_t res;
417 if(!soc_desc_evaluate_formula(formula, map, res, err))
418 {
419 qDebug() << "Cannot evaluator " << QString::fromStdString(formula)
420 << "for n=" << n << ": " << QString::fromStdString(err);
421 return;
422 }
423 std::string regname = name;
424 std::string strn = QString("%1").arg(n).toStdString();
425 regname.replace(pos, 1, strn);
426 list.push_back(std::make_pair(regname, res));
427 }
428 // everything went good, commit result
429 while(m_instances_table->rowCount() > 1)
430 m_instances_table->removeRow(0);
431 m_ref.GetReg().addr.resize(list.size());
432 for(size_t i = 0; i < list.size(); i++)
433 {
434 m_instances_table->insertRow(i);
435 m_ref.GetReg().addr[i].name = list[i].first;
436 m_ref.GetReg().addr[i].addr = list[i].second;
437 FillRow(i, m_ref.GetReg().addr[i]);
438 }
439}
440
441void RegEditPanel::OnFormulaChanged(int index)
442{
443 if(index == -1)
444 return;
445 m_ref.GetReg().formula.type = static_cast< soc_reg_formula_type_t >(m_formula_combo->itemData(index).toInt());
446 UpdateFormula();
447 emit OnModified(true);
448}
449
450void RegEditPanel::UpdateFormula()
451{
452 m_formula_string_edit->hide();
453 m_formula_string_gen->hide();
454 switch(m_ref.GetReg().formula.type)
455 {
456 case REG_FORMULA_STRING:
457 m_formula_string_edit->show();
458 m_formula_string_gen->show();
459 break;
460 case REG_FORMULA_NONE:
461 default:
462 break;
463 }
464}
465
466void RegEditPanel::OnSctEdited(int state)
467{
468 if(state == Qt::Checked)
469 m_ref.GetReg().flags |= REG_HAS_SCT;
470 else
471 m_ref.GetReg().flags &= ~REG_HAS_SCT;
472 emit OnModified(true);
473}
474
475void RegEditPanel::FillRow(int row, const soc_reg_addr_t& addr)
476{
477 QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(addr.name));
478 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
479 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
480 m_instances_table->setItem(row, RegInstNameColumn, item);
481 item = new QTableWidgetItem();
482 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
483 item->setData(Qt::DisplayRole, QVariant(addr.addr));
484 m_instances_table->setItem(row, RegInstAddrColumn, item);
485 item = new QTableWidgetItem(QIcon::fromTheme("list-remove"), "", RegInstDeleteType);
486 item->setToolTip("Remove?");
487 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
488 m_instances_table->setItem(row, RegInstIconColumn, item);
489}
490
491void RegEditPanel::CreateNewAddrRow(int row)
492{
493 QTableWidgetItem *item = new QTableWidgetItem(QIcon::fromTheme("list-add"), "", RegInstNewType);
494 item->setToolTip("New?");
495 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
496 m_instances_table->setItem(row, RegInstIconColumn, item);
497 item = new QTableWidgetItem("New instance...");
498 QFont font = item->font();
499 font.setItalic(true);
500 item->setFont(font);
501 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
502 m_instances_table->setItem(row, RegInstNameColumn, item);
503 item = new QTableWidgetItem("");
504 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
505 m_instances_table->setItem(row, RegInstAddrColumn, item);
506}
507
508void RegEditPanel::OnNameEdited(const QString& text)
509{
510 m_ref.GetReg().name = text.toStdString();
511 emit OnModified(m_name_edit->isModified());
512}
513
514void RegEditPanel::OnDescEdited()
515{
516 m_ref.GetReg().desc = m_desc_edit->GetTextHtml().toStdString();
517 emit OnModified(m_desc_edit->IsModified());
518}
519
520void RegEditPanel::OnInstActivated(int row, int column)
521{
522 if(column != 0)
523 return;
524 int type = m_instances_table->item(row, column)->type();
525 if(type == RegInstDeleteType)
526 {
527 m_ref.GetReg().addr.erase(m_ref.GetReg().addr.begin() + row);
528 m_instances_table->removeRow(row);
529 }
530 else if(type == RegInstNewType)
531 {
532 m_instances_table->insertRow(row);
533 soc_reg_addr_t addr;
534 addr.name = QString("UNNAMED_%1").arg(row).toStdString();
535 addr.addr = 0;
536 m_ref.GetReg().addr.push_back(addr);
537 FillRow(row, addr);
538 }
539}
540
541void RegEditPanel::OnInstChanged(int row, int column)
542{
543 /* ignore extra row for addition */
544 if(row >= (int)m_ref.GetReg().addr.size())
545 return;
546 QTableWidgetItem *item = m_instances_table->item(row, column);
547 if(column == RegInstNameColumn)
548 {
549 m_ref.GetReg().addr[row].name = item->text().toStdString();
550 emit OnModified(true);
551 }
552 else if(column == RegInstAddrColumn)
553 {
554 m_ref.GetReg().addr[row].addr = item->data(Qt::DisplayRole).toUInt();
555 emit OnModified(true);
556 }
557}
558
559/**
560 * FieldEditPanel
561 */
562FieldEditPanel::FieldEditPanel(SocFieldRef ref, QWidget *parent)
563 :QWidget(parent), m_ref(ref)
564{
565 m_name_group = new QGroupBox("Name", this);
566 m_name_edit = new QLineEdit(this);
567 m_name_edit->setText(QString::fromStdString(ref.GetField().name));
568 QVBoxLayout *name_group_layout = new QVBoxLayout;
569 name_group_layout->addWidget(m_name_edit);
570 m_name_group->setLayout(name_group_layout);
571
572 m_bitrange_group = new QGroupBox("Bit Range", this);
573 m_bitrange_edit = new QLineEdit(this);
574 const soc_reg_field_t& field = ref.GetField();
575 QString bits_str;
576 if(field.first_bit == field.last_bit)
577 bits_str.sprintf("%d", field.first_bit);
578 else
579 bits_str.sprintf("%d:%d", field.last_bit, field.first_bit);
580 m_bitrange_edit->setText(bits_str);
581 m_bitrange_edit->setValidator(new SocBitRangeValidator(m_bitrange_edit));
582 QVBoxLayout *bitrange_group_layout = new QVBoxLayout;
583 bitrange_group_layout->addWidget(m_bitrange_edit);
584 m_bitrange_group->setLayout(bitrange_group_layout);
585
586 m_desc_group = new QGroupBox("Description", this);
587 QHBoxLayout *group_layout = new QHBoxLayout;
588 m_desc_edit = new MyTextEditor(this);
589 m_desc_edit->SetTextHtml(QString::fromStdString(ref.GetField().desc));
590 group_layout->addWidget(m_desc_edit);
591 m_desc_group->setLayout(group_layout);
592
593 m_value_group = new QGroupBox("Values", this);
594 QHBoxLayout *value_layout = new QHBoxLayout;
595 m_value_table = new QTableWidget(this);
596 m_value_table->setRowCount(ref.GetField().value.size() + 1);
597 m_value_table->setColumnCount(FieldValueNrColumns);
598 for(size_t row = 0; row < ref.GetField().value.size(); row++)
599 FillRow(row, ref.GetField().value[row]);
600 CreateNewRow(ref.GetField().value.size());
601 m_value_table->setHorizontalHeaderItem(FieldValueIconColumn, new QTableWidgetItem(""));
602 m_value_table->setHorizontalHeaderItem(FieldValueNameColumn, new QTableWidgetItem("Name"));
603 m_value_table->setHorizontalHeaderItem(FieldValueValueColumn, new QTableWidgetItem("Value"));
604 m_value_table->setHorizontalHeaderItem(FieldValueDescColumn, new QTableWidgetItem("Description"));
605 m_value_table->verticalHeader()->setVisible(false);
606 m_value_table->horizontalHeader()->setStretchLastSection(true);
607 value_layout->addWidget(m_value_table);
608 m_value_group->setLayout(value_layout);
609
610 QHBoxLayout *line_layout = new QHBoxLayout;
611 line_layout->addWidget(m_name_group);
612 line_layout->addWidget(m_bitrange_group);
613 line_layout->addStretch();
614
615 QVBoxLayout *left_layout = new QVBoxLayout;
616 left_layout->addLayout(line_layout);
617 left_layout->addWidget(m_desc_group);
618 left_layout->addWidget(m_value_group, 1);
619
620 UpdateDelegates();
621
622 connect(m_name_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnNameEdited(const QString&)));
623 connect(m_desc_edit, SIGNAL(OnTextChanged()), this, SLOT(OnDescEdited()));
624 connect(m_value_table, SIGNAL(cellActivated(int,int)), this, SLOT(OnValueActivated(int,int)));
625 connect(m_value_table, SIGNAL(cellChanged(int,int)), this, SLOT(OnValueChanged(int,int)));
626 connect(m_bitrange_edit, SIGNAL(textChanged(const QString&)), this, SLOT(OnBitRangeEdited(const QString&)));
627
628 setLayout(left_layout);
629}
630
631void FieldEditPanel::UpdateDelegates()
632{
633 SocFieldItemDelegate *m_table_delegate = new SocFieldItemDelegate(m_ref.GetField(), this);
634 QItemEditorFactory *m_table_edit_factory = new QItemEditorFactory();
635 SocFieldEditorCreator *m_table_edit_creator = new SocFieldEditorCreator(m_ref.GetField());
636 m_table_edit_factory->registerEditor(QVariant::UInt, m_table_edit_creator);
637 m_table_delegate->setItemEditorFactory(m_table_edit_factory);
638 m_value_table->setItemDelegate(m_table_delegate);
639 m_value_table->resizeColumnsToContents();
640}
641
642void FieldEditPanel::UpdateWarning(int row)
643{
644 soc_word_t val = m_ref.GetField().value[row].value;
645 soc_word_t max = m_ref.GetField().bitmask() >> m_ref.GetField().first_bit;
646 QTableWidgetItem *item = m_value_table->item(row, FieldValueValueColumn);
647 if(val > max)
648 {
649 item->setIcon(QIcon::fromTheme("dialog-warning"));
650 item->setToolTip("Value is too big for the field");
651 }
652 else
653 {
654 item->setIcon(QIcon());
655 item->setToolTip("");
656 }
657}
658
659void FieldEditPanel::FillRow(int row, const soc_reg_field_value_t& val)
660{
661 QTableWidgetItem *item = new QTableWidgetItem(QString::fromStdString(val.name));
662 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
663 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
664 m_value_table->setItem(row, FieldValueNameColumn, item);
665 item = new QTableWidgetItem();
666 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
667 item->setData(Qt::DisplayRole, QVariant(val.value));
668 m_value_table->setItem(row, FieldValueValueColumn, item);
669 item = new QTableWidgetItem(QString::fromStdString(val.desc));
670 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable);
671 m_value_table->setItem(row, FieldValueDescColumn, item);
672 item = new QTableWidgetItem(QIcon::fromTheme("list-remove"), "", FieldValueDeleteType);
673 item->setToolTip("Remove?");
674 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
675 m_value_table->setItem(row, FieldValueIconColumn, item);
676 UpdateWarning(row);
677}
678
679void FieldEditPanel::CreateNewRow(int row)
680{
681 QTableWidgetItem *item = new QTableWidgetItem(QIcon::fromTheme("list-add"), "", FieldValueNewType);
682 item->setToolTip("New?");
683 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
684 m_value_table->setItem(row, FieldValueIconColumn, item);
685 item = new QTableWidgetItem("New value...");
686 QFont font = item->font();
687 font.setItalic(true);
688 item->setFont(font);
689 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
690 m_value_table->setItem(row, FieldValueNameColumn, item);
691}
692
693void FieldEditPanel::OnBitRangeEdited(const QString& input)
694{
695 const SocBitRangeValidator *validator =
696 dynamic_cast< const SocBitRangeValidator *>(m_bitrange_edit->validator());
697 int first, last;
698 QValidator::State state = validator->parse(input, last, first);
699 if(state != QValidator::Acceptable)
700 return;
701 m_ref.GetField().first_bit = first;
702 m_ref.GetField().last_bit = last;
703 // update all warning signs
704 for(size_t row = 0; row < m_ref.GetField().value.size(); row++)
705 UpdateWarning(row);
706 // also updates delegates because they now have the wrong view of the field
707 UpdateDelegates();
708 emit OnModified(true);
709}
710
711void FieldEditPanel::OnNameEdited(const QString& text)
712{
713 m_ref.GetField().name = text.toStdString();
714 emit OnModified(m_name_edit->isModified());
715}
716
717void FieldEditPanel::OnDescEdited()
718{
719 m_ref.GetField().desc = m_desc_edit->GetTextHtml().toStdString();
720 emit OnModified(m_desc_edit->IsModified());
721}
722
723void FieldEditPanel::OnValueActivated(int row, int column)
724{
725 if(column != 0)
726 return;
727 int type = m_value_table->item(row, column)->type();
728 if(type == FieldValueDeleteType)
729 {
730 m_ref.GetField().value.erase(m_ref.GetField().value.begin() + row);
731 m_value_table->removeRow(row);
732 }
733 else if(type == FieldValueNewType)
734 {
735 m_value_table->insertRow(row);
736 soc_reg_field_value_t val;
737 val.name = QString("UNNAMED_%1").arg(row).toStdString();
738 val.value = 0;
739 m_ref.GetField().value.push_back(val);
740 FillRow(row, val);
741 }
742}
743
744void FieldEditPanel::OnValueChanged(int row, int column)
745{
746 /* ignore extra row for addition */
747 if(row >= (int)m_ref.GetField().value.size())
748 return;
749 QTableWidgetItem *item = m_value_table->item(row, column);
750 if(column == FieldValueNameColumn)
751 m_ref.GetField().value[row].name = item->text().toStdString();
752 else if(column == FieldValueValueColumn)
753 {
754 soc_word_t& fval = m_ref.GetField().value[row].value;
755 soc_word_t new_val = item->data(Qt::DisplayRole).toUInt();
756 /* avoid infinite recursion by calling UpdateWarning() when
757 * only the icon changes which would trigger this callback again */
758 if(fval != new_val)
759 {
760 fval = new_val;
761 UpdateWarning(row);
762 }
763 }
764 else if(column == FieldValueDescColumn)
765 m_ref.GetField().value[row].desc = item->text().toStdString();
766 emit OnModified(true);
767}
768
769namespace
770{
771
772enum
773{
774 SocTreeSocType = QTreeWidgetItem::UserType,
775 SocTreeDevType,
776 SocTreeRegType,
777 SocTreeFieldType,
778 SocTreeNewDevType,
779 SocTreeNewRegType,
780 SocTreeNewFieldType,
781};
782
783/**
784 * SocTreeItem
785 */
786
787class SocTreeItem : public QTreeWidgetItem
788{
789public:
790 SocTreeItem(const QString& string, const SocRef& ref)
791 :QTreeWidgetItem(QStringList(string), SocTreeSocType), m_ref(ref) {}
792
793 const SocRef& GetRef() { return m_ref; }
794private:
795 SocRef m_ref;
796};
797
798/**
799 * NewDevTreeItem
800 */
801
802class NewDevTreeItem : public QTreeWidgetItem
803{
804public:
805 NewDevTreeItem(const QString& string, const SocRef& ref)
806 :QTreeWidgetItem(QStringList(string), SocTreeNewDevType), m_ref(ref) {}
807
808 const SocRef& GetRef() { return m_ref; }
809private:
810 SocRef m_ref;
811};
812
813/**
814 * DevTreeItem
815 */
816
817class DevTreeItem : public QTreeWidgetItem
818{
819public:
820 DevTreeItem(const QString& string, const SocDevRef& ref)
821 :QTreeWidgetItem(QStringList(string), SocTreeDevType), m_ref(ref) {}
822
823 const SocDevRef& GetRef() { return m_ref; }
824private:
825 SocDevRef m_ref;
826};
827
828/**
829 * NewRegTreeItem
830 */
831
832class NewRegTreeItem : public QTreeWidgetItem
833{
834public:
835 NewRegTreeItem(const QString& string, const SocDevRef& ref)
836 :QTreeWidgetItem(QStringList(string), SocTreeNewRegType), m_ref(ref) {}
837
838 const SocDevRef& GetRef() { return m_ref; }
839private:
840 SocDevRef m_ref;
841};
842
843/**
844 * RegTreeItem
845 */
846
847class RegTreeItem : public QTreeWidgetItem
848{
849public:
850 RegTreeItem(const QString& string, const SocRegRef& ref)
851 :QTreeWidgetItem(QStringList(string), SocTreeRegType), m_ref(ref) {}
852
853 const SocRegRef& GetRef() { return m_ref; }
854private:
855 SocRegRef m_ref;
856};
857
858/**
859 * NewFieldTreeItem
860 */
861
862class NewFieldTreeItem : public QTreeWidgetItem
863{
864public:
865 NewFieldTreeItem(const QString& string, const SocRegRef& ref)
866 :QTreeWidgetItem(QStringList(string), SocTreeNewFieldType), m_ref(ref) {}
867
868 const SocRegRef& GetRef() { return m_ref; }
869private:
870 SocRegRef m_ref;
871};
872
873/**
874 * FieldTreeItem
875 */
876
877class FieldTreeItem : public QTreeWidgetItem
878{
879public:
880 FieldTreeItem(const QString& string, const SocFieldRef& ref)
881 :QTreeWidgetItem(QStringList(string), SocTreeFieldType), m_ref(ref) {}
882
883 const SocFieldRef& GetRef() { return m_ref; }
884private:
885 SocFieldRef m_ref;
886};
887
888}
889
890/**
891 * RegEdit
892 */
893RegEdit::RegEdit(Backend *backend, QWidget *parent)
894 :QWidget(parent), m_backend(backend)
895{
896 QVBoxLayout *m_vert_layout = new QVBoxLayout();
897 m_file_group = new QGroupBox("File selection", this);
898 QHBoxLayout *m_file_group_layout = new QHBoxLayout();
899 m_file_edit = new QLineEdit(this);
900 m_file_edit->setReadOnly(true);
901 m_file_open = new QToolButton(this);
902 m_file_open->setText("Open");
903 m_file_open->setIcon(QIcon::fromTheme("document-open"));
904 m_file_open->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
905 QMenu *file_open_menu = new QMenu(this);
906 QAction *new_act = file_open_menu->addAction(QIcon::fromTheme("document-new"), "New...");
907 m_file_open->setMenu(file_open_menu);
908
909 m_file_save = new QToolButton(this);
910 m_file_save->setText("Save");
911 m_file_save->setIcon(QIcon::fromTheme("document-save"));
912 m_file_save->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
913 QMenu *file_save_menu = new QMenu(this);
914 QAction *saveas_act = file_save_menu->addAction(QIcon::fromTheme("document-save-as"), "Save as...");
915 m_file_save->setMenu(file_save_menu);
916 m_file_group_layout->addWidget(m_file_open);
917 m_file_group_layout->addWidget(m_file_save);
918 m_file_group_layout->addWidget(m_file_edit);
919
920 m_splitter = new QSplitter(this);
921 m_soc_tree = new QTreeWidget(this);
922 m_soc_tree->setColumnCount(1);
923 m_soc_tree->setHeaderLabel(QString("Name"));
924 m_splitter->addWidget(m_soc_tree);
925 m_splitter->setStretchFactor(0, 0);
926
927 m_file_group->setLayout(m_file_group_layout);
928 m_vert_layout->addWidget(m_file_group);
929 m_vert_layout->addWidget(m_splitter, 1);
930
931 setLayout(m_vert_layout);
932
933 SetModified(false, false);
934 m_right_panel = 0;
935 SetPanel(new EmptyEditPanel(this));
936
937 connect(m_file_open, SIGNAL(clicked()), this, SLOT(OnOpen()));
938 connect(m_file_save, SIGNAL(clicked()), this, SLOT(OnSave()));
939 connect(new_act, SIGNAL(triggered()), this, SLOT(OnNew()));
940 connect(saveas_act, SIGNAL(triggered()), this, SLOT(OnSaveAs()));
941 connect(m_soc_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
942 this, SLOT(OnSocItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
943 connect(m_soc_tree, SIGNAL(itemActivated(QTreeWidgetItem*, int)),
944 this, SLOT(OnSocItemActivated(QTreeWidgetItem*, int)));
945}
946
947RegEdit::~RegEdit()
948{
949}
950
951void RegEdit::OnSave()
952{
953 SaveSoc();
954}
955
956void RegEdit::OnSaveAs()
957{
958 SaveSocAs();
959}
960
961bool RegEdit::CloseSoc()
962{
963 if(!m_modified)
964 return true;
965 QMessageBox msgBox;
966 msgBox.setText("The description has been modified.");
967 msgBox.setInformativeText("Do you want to save your changes?");
968 msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
969 msgBox.setDefaultButton(QMessageBox::Save);
970 int ret = msgBox.exec();
971 if(ret == QMessageBox::Discard)
972 return true;
973 if(ret == QMessageBox::Cancel)
974 return false;
975 return SaveSoc();
976}
977
978bool RegEdit::SaveSoc()
979{
980 if(m_file_edit->text().size() == 0)
981 return SaveSocAs();
982 else
983 return SaveSocFile(m_file_edit->text());
984}
985
986bool RegEdit::GetFilename(QString& filename, bool save)
987{
988 QFileDialog *fd = new QFileDialog(this);
989 if(save)
990 fd->setAcceptMode(QFileDialog::AcceptSave);
991 fd->setFilter("Description files (*.xml);;All files (*)");
992 fd->setDirectory(Settings::Get()->value("loaddescdir", QDir::currentPath()).toString());
993 if(fd->exec())
994 {
995 QStringList filenames = fd->selectedFiles();
996 filename = filenames[0];
997 Settings::Get()->setValue("loaddescdir", fd->directory().absolutePath());
998 return true;
999 }
1000 else
1001 return false;
1002}
1003
1004bool RegEdit::SaveSocAs()
1005{
1006 QString filename;
1007 if(!GetFilename(filename, true))
1008 return false;
1009 m_file_edit->setText(filename);
1010 return SaveSocFile(filename);
1011}
1012
1013void RegEdit::OnOpen()
1014{
1015 if(!CloseSoc())
1016 return;
1017 QString filename;
1018 if(!GetFilename(filename, false))
1019 return;
1020 LoadSocFile(filename);
1021}
1022
1023void RegEdit::OnNew()
1024{
1025 if(!CloseSoc())
1026 return;
1027 m_cur_socfile = SocFile();
1028 m_file_edit->setText("");
1029 SetModified(false, false);
1030 UpdateSocFile();
1031}
1032
1033bool RegEdit::SaveSocFile(const QString& filename)
1034{
1035 soc_desc_normalize(m_cur_socfile.GetSoc());
1036 if(!soc_desc_produce_xml(filename.toStdString(), m_cur_socfile.GetSoc()))
1037 {
1038 QMessageBox::warning(this, "The description was not saved",
1039 "There was an error when saving the file");
1040 return false;
1041 }
1042 m_soc_tree->clear();
1043 FillSocTree();
1044 SetModified(false, false);
1045 return true;
1046}
1047
1048void RegEdit::LoadSocFile(const QString& filename)
1049{
1050 m_cur_socfile = SocFile(filename);
1051 if(!m_cur_socfile.IsValid())
1052 {
1053 QMessageBox::warning(this, "The description was not loaded",
1054 "There was an error when loading the file");
1055 return;
1056 }
1057 m_file_edit->setText(filename);
1058 SetModified(false, false);
1059 UpdateSocFile();
1060}
1061
1062void RegEdit::CreateNewFieldItem(QTreeWidgetItem *_parent)
1063{
1064 RegTreeItem *parent = dynamic_cast< RegTreeItem* >(_parent);
1065 NewFieldTreeItem *newdev_item = new NewFieldTreeItem("New field...", parent->GetRef());
1066 MakeItalic(newdev_item, true);
1067 newdev_item->setIcon(0, QIcon::fromTheme("list-add"));
1068 parent->addChild(newdev_item);
1069}
1070
1071void RegEdit::FillRegTreeItem(QTreeWidgetItem *_item)
1072{
1073 RegTreeItem *item = dynamic_cast< RegTreeItem* >(_item);
1074 const soc_reg_t& reg = item->GetRef().GetReg();
1075 for(size_t i = 0; i < reg.field.size(); i++)
1076 {
1077 const soc_reg_field_t& field = reg.field[i];
1078 FieldTreeItem *field_item = new FieldTreeItem(QString::fromStdString(field.name),
1079 SocFieldRef(item->GetRef(), i));
1080 FixupEmptyItem(field_item);
1081 item->addChild(field_item);
1082 }
1083 CreateNewFieldItem(item);
1084}
1085
1086void RegEdit::CreateNewRegisterItem(QTreeWidgetItem *_parent)
1087{
1088 DevTreeItem *parent = dynamic_cast< DevTreeItem* >(_parent);
1089 NewRegTreeItem *newdev_item = new NewRegTreeItem("New register...", parent->GetRef());
1090 MakeItalic(newdev_item, true);
1091 newdev_item->setIcon(0, QIcon::fromTheme("list-add"));
1092 parent->addChild(newdev_item);
1093}
1094
1095void RegEdit::FillDevTreeItem(QTreeWidgetItem *_item)
1096{
1097 DevTreeItem *item = dynamic_cast< DevTreeItem* >(_item);
1098 const soc_dev_t& dev = item->GetRef().GetDev();
1099 for(size_t i = 0; i < dev.reg.size(); i++)
1100 {
1101 const soc_reg_t& reg = dev.reg[i];
1102 RegTreeItem *reg_item = new RegTreeItem(QString::fromStdString(reg.name),
1103 SocRegRef(item->GetRef(), i, -1));
1104 FixupEmptyItem(reg_item);
1105 FillRegTreeItem(reg_item);
1106 item->addChild(reg_item);
1107 }
1108 CreateNewRegisterItem(item);
1109}
1110
1111void RegEdit::CreateNewDeviceItem(QTreeWidgetItem *_parent)
1112{
1113 SocTreeItem *parent = dynamic_cast< SocTreeItem* >(_parent);
1114 NewDevTreeItem *newdev_item = new NewDevTreeItem("New device...", parent->GetRef());
1115 MakeItalic(newdev_item, true);
1116 newdev_item->setIcon(0, QIcon::fromTheme("list-add"));
1117 parent->addChild(newdev_item);
1118}
1119
1120void RegEdit::FillSocTreeItem(QTreeWidgetItem *_item)
1121{
1122 SocTreeItem *item = dynamic_cast< SocTreeItem* >(_item);
1123 const soc_t& soc = item->GetRef().GetSoc();
1124 for(size_t i = 0; i < soc.dev.size(); i++)
1125 {
1126 const soc_dev_t& reg = soc.dev[i];
1127 DevTreeItem *dev_item = new DevTreeItem(QString::fromStdString(reg.name),
1128 SocDevRef(item->GetRef(), i, -1));
1129 FixupEmptyItem(dev_item);
1130 FillDevTreeItem(dev_item);
1131 item->addChild(dev_item);
1132 }
1133 CreateNewDeviceItem(item);
1134}
1135
1136void RegEdit::FillSocTree()
1137{
1138 SocRef ref = m_cur_socfile.GetSocRef();
1139 SocTreeItem *soc_item = new SocTreeItem(
1140 QString::fromStdString(ref.GetSoc().name), ref);
1141 FixupEmptyItem(soc_item);
1142 FillSocTreeItem(soc_item);
1143 m_soc_tree->addTopLevelItem(soc_item);
1144 soc_item->setExpanded(true);
1145}
1146
1147void RegEdit::MakeItalic(QTreeWidgetItem *item, bool it)
1148{
1149 QFont font = item->font(0);
1150 font.setItalic(it);
1151 item->setFont(0, font);
1152}
1153
1154void RegEdit::FixupEmptyItem(QTreeWidgetItem *item)
1155{
1156 if(item->text(0).size() == 0)
1157 {
1158 item->setIcon(0, QIcon::fromTheme("dialog-error"));
1159 MakeItalic(item, true);
1160 item->setText(0, "Unnamed");
1161 }
1162 else
1163 {
1164 item->setIcon(0, QIcon::fromTheme("cpu"));
1165 MakeItalic(item, false);
1166 }
1167}
1168
1169void RegEdit::UpdateSocFile()
1170{
1171 m_soc_tree->clear();
1172 FillSocTree();
1173 SetPanel(new EmptyEditPanel(this));
1174}
1175
1176void RegEdit::SetPanel(QWidget *panel)
1177{
1178 delete m_right_panel;
1179 m_right_panel = panel;
1180 connect(m_right_panel, SIGNAL(OnModified(bool)), this, SLOT(OnSocModified(bool)));
1181 m_splitter->addWidget(m_right_panel);
1182 m_splitter->setStretchFactor(1, 2);
1183}
1184
1185void RegEdit::SetModified(bool add, bool mod)
1186{
1187 m_modified = add ? (m_modified || mod) : mod;
1188 emit OnModified(mod);
1189}
1190
1191void RegEdit::OnSocModified(bool modified)
1192{
1193 // we might need to update the name in the tree
1194 UpdateName(m_soc_tree->currentItem());
1195 if(modified)
1196 SetModified(true, true);
1197}
1198
1199void RegEdit::DisplaySoc(SocRef ref)
1200{
1201 SetPanel(new SocEditPanel(ref, this));
1202}
1203
1204void RegEdit::DisplayDev(SocDevRef ref)
1205{
1206 SetPanel(new DevEditPanel(ref, this));
1207}
1208
1209void RegEdit::DisplayReg(SocRegRef ref)
1210{
1211 SetPanel(new RegEditPanel(ref, this));
1212}
1213
1214void RegEdit::DisplayField(SocFieldRef ref)
1215{
1216 SetPanel(new FieldEditPanel(ref, this));
1217}
1218
1219void RegEdit::UpdateName(QTreeWidgetItem *current)
1220{
1221 if(current == 0)
1222 return;
1223 if(current->type() == SocTreeSocType)
1224 {
1225 SocTreeItem *item = dynamic_cast< SocTreeItem * >(current);
1226 item->setText(0, QString::fromStdString(item->GetRef().GetSoc().name));
1227 }
1228 else if(current->type() == SocTreeDevType)
1229 {
1230 DevTreeItem *item = dynamic_cast< DevTreeItem * >(current);
1231 item->setText(0, QString::fromStdString(item->GetRef().GetDev().name));
1232 }
1233 else if(current->type() == SocTreeRegType)
1234 {
1235 RegTreeItem *item = dynamic_cast< RegTreeItem * >(current);
1236 item->setText(0, QString::fromStdString(item->GetRef().GetReg().name));
1237 }
1238 else if(current->type() == SocTreeFieldType)
1239 {
1240 FieldTreeItem *item = dynamic_cast< FieldTreeItem * >(current);
1241 item->setText(0, QString::fromStdString(item->GetRef().GetField().name));
1242 }
1243 FixupEmptyItem(current);
1244}
1245
1246void RegEdit::OnSocItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
1247{
1248 Q_UNUSED(previous);
1249 if(current == 0)
1250 return;
1251 if(current->type() == SocTreeSocType)
1252 {
1253 SocTreeItem *item = dynamic_cast< SocTreeItem * >(current);
1254 DisplaySoc(item->GetRef());
1255 }
1256 else if(current->type() == SocTreeDevType)
1257 {
1258 DevTreeItem *item = dynamic_cast< DevTreeItem * >(current);
1259 DisplayDev(item->GetRef());
1260 }
1261 else if(current->type() == SocTreeRegType)
1262 {
1263 RegTreeItem *item = dynamic_cast< RegTreeItem * >(current);
1264 DisplayReg(item->GetRef());
1265 }
1266 else if(current->type() == SocTreeFieldType)
1267 {
1268 FieldTreeItem *item = dynamic_cast< FieldTreeItem * >(current);
1269 DisplayField(item->GetRef());
1270 }
1271}
1272
1273void RegEdit::OnSocItemActivated(QTreeWidgetItem *current, int column)
1274{
1275 Q_UNUSED(column);
1276 if(current == 0)
1277 return;
1278 if(current->type() == SocTreeNewDevType)
1279 AddDevice(current);
1280 else if(current->type() == SocTreeNewRegType)
1281 AddRegister(current);
1282 else if(current->type() == SocTreeNewFieldType)
1283 AddField(current);
1284}
1285
1286void RegEdit::AddDevice(QTreeWidgetItem *_item)
1287{
1288 NewDevTreeItem *item = dynamic_cast< NewDevTreeItem * >(_item);
1289 item->GetRef().GetSoc().dev.push_back(soc_dev_t());
1290 DevTreeItem *dev_item = new DevTreeItem("",
1291 SocDevRef(item->GetRef(), item->GetRef().GetSoc().dev.size() - 1, -1));
1292 FixupEmptyItem(dev_item);
1293 item->parent()->insertChild(item->parent()->indexOfChild(item), dev_item);
1294 CreateNewRegisterItem(dev_item);
1295 m_soc_tree->setCurrentItem(dev_item);
1296}
1297
1298void RegEdit::AddRegister(QTreeWidgetItem *_item)
1299{
1300 NewRegTreeItem *item = dynamic_cast< NewRegTreeItem * >(_item);
1301 item->GetRef().GetDev().reg.push_back(soc_reg_t());
1302 RegTreeItem *reg_item = new RegTreeItem("",
1303 SocRegRef(item->GetRef(), item->GetRef().GetDev().reg.size() - 1, -1));
1304 FixupEmptyItem(reg_item);
1305 item->parent()->insertChild(item->parent()->indexOfChild(item), reg_item);
1306 CreateNewFieldItem(reg_item);
1307 m_soc_tree->setCurrentItem(reg_item);
1308}
1309
1310void RegEdit::AddField(QTreeWidgetItem *_item)
1311{
1312 NewFieldTreeItem *item = dynamic_cast< NewFieldTreeItem * >(_item);
1313 item->GetRef().GetReg().field.push_back(soc_reg_field_t());
1314 FieldTreeItem *field_item = new FieldTreeItem("",
1315 SocFieldRef(item->GetRef(), item->GetRef().GetReg().field.size() - 1));
1316 FixupEmptyItem(field_item);
1317 item->parent()->insertChild(item->parent()->indexOfChild(item), field_item);
1318 m_soc_tree->setCurrentItem(field_item);
1319}
1320
1321bool RegEdit::Quit()
1322{
1323 return CloseSoc();
1324} \ No newline at end of file
diff --git a/utils/regtools/qeditor/regedit.h b/utils/regtools/qeditor/regedit.h
new file mode 100644
index 0000000000..8615816783
--- /dev/null
+++ b/utils/regtools/qeditor/regedit.h
@@ -0,0 +1,282 @@
1#ifndef REGEDIT_H
2#define REGEDIT_H
3
4#include <QComboBox>
5#include <QTreeWidget>
6#include <QVBoxLayout>
7#include <QTabWidget>
8#include <QSplitter>
9#include <QLineEdit>
10#include <QPushButton>
11#include <QLabel>
12#include <QListWidget>
13#include <QGroupBox>
14#include <QToolButton>
15#include <QMenu>
16#include <QCheckBox>
17#include <QRadioButton>
18#include <QButtonGroup>
19#include <QDebug>
20#include <QScrollArea>
21#include "backend.h"
22#include "settings.h"
23#include "mainwindow.h"
24#include "aux.h"
25
26class AbstractRegEditPanel
27{
28public:
29 AbstractRegEditPanel() {}
30 virtual ~AbstractRegEditPanel() {}
31 virtual void OnModified(bool mod) = 0;
32};
33
34class EmptyEditPanel : public QWidget, public AbstractRegEditPanel
35{
36 Q_OBJECT
37public:
38 EmptyEditPanel(QWidget *parent);
39
40signals:
41 void OnModified(bool mod);
42
43protected:
44};
45
46class SocEditPanel : public QWidget, public AbstractRegEditPanel
47{
48 Q_OBJECT
49public:
50 SocEditPanel(SocRef ref, QWidget *parent = 0);
51
52signals:
53 void OnModified(bool mod);
54
55protected slots:
56 void OnTextEdited();
57 void OnNameEdited(const QString& text);
58
59protected:
60 SocRef m_ref;
61 QGroupBox *m_name_group;
62 QLineEdit *m_name_edit;
63 QGroupBox *m_desc_group;
64 MyTextEditor *m_desc_edit;
65};
66
67class DevEditPanel : public QWidget, public AbstractRegEditPanel
68{
69 Q_OBJECT
70public:
71 DevEditPanel(SocDevRef ref, QWidget *parent = 0);
72
73signals:
74 void OnModified(bool mod);
75
76protected slots:
77 void OnInstActivated(int row, int column);
78 void OnInstChanged(int row, int column);
79 void OnNameEdited(const QString& text);
80 void OnLongNameEdited(const QString& text);
81 void OnVersionEdited(const QString& text);
82 void OnDescEdited();
83
84protected:
85 void FillRow(int row, const soc_dev_addr_t& addr);
86 void CreateNewRow(int row);
87
88 enum
89 {
90 DevInstDeleteType = QTableWidgetItem::UserType,
91 DevInstNewType
92 };
93
94 enum
95 {
96 DevInstIconColumn = 0,
97 DevInstNameColumn = 1,
98 DevInstAddrColumn = 2,
99 };
100
101 SocDevRef m_ref;
102 QGroupBox *m_name_group;
103 QLineEdit *m_name_edit;
104 QGroupBox *m_long_name_group;
105 QLineEdit *m_long_name_edit;
106 QGroupBox *m_version_group;
107 QLineEdit *m_version_edit;
108 QGroupBox *m_instances_group;
109 QTableWidget *m_instances_table;
110 QGroupBox *m_desc_group;
111 MyTextEditor *m_desc_edit;
112};
113
114class RegEditPanel : public QWidget, public AbstractRegEditPanel
115{
116 Q_OBJECT
117public:
118 RegEditPanel(SocRegRef ref, QWidget *parent = 0);
119
120signals:
121 void OnModified(bool mod);
122
123protected slots:
124 void OnInstActivated(int row, int column);
125 void OnInstChanged(int row, int column);
126 void OnNameEdited(const QString& text);
127 void OnDescEdited();
128 void OnSctEdited(int state);
129 void OnFormulaChanged(int index);
130 void OnFormulaStringChanged(const QString& text);
131 void OnFormulaGenerate(bool checked);
132
133protected:
134 void CreateNewAddrRow(int row);
135 void FillRow(int row, const soc_reg_addr_t& addr);
136 void UpdateFormula();
137 void UpdateWarning(int row);
138
139 enum
140 {
141 RegInstDeleteType = QTableWidgetItem::UserType,
142 RegInstNewType
143 };
144
145 enum
146 {
147 RegInstIconColumn = 0,
148 RegInstNameColumn,
149 RegInstAddrColumn,
150 RegInstNrColumns,
151 };
152
153 SocRegRef m_ref;
154 QGroupBox *m_name_group;
155 QLineEdit *m_name_edit;
156 QGroupBox *m_instances_group;
157 QTableWidget *m_instances_table;
158 QGroupBox *m_desc_group;
159 QGroupBox *m_flags_group;
160 QCheckBox *m_sct_check;
161 QFont m_reg_font;
162 QGroupBox *m_formula_group;
163 QButtonGroup *m_formula_radio_group;
164 QLabel *m_formula_type_label;
165 QComboBox *m_formula_combo;
166 QLineEdit *m_formula_string_edit;
167 QPushButton *m_formula_string_gen;
168 RegSexyDisplay *m_sexy_display;
169 MyTextEditor *m_desc_edit;
170 QGroupBox *m_field_group;
171 QTableWidget *m_field_table;
172};
173
174class FieldEditPanel : public QWidget, public AbstractRegEditPanel
175{
176 Q_OBJECT
177public:
178 FieldEditPanel(SocFieldRef ref, QWidget *parent = 0);
179
180signals:
181 void OnModified(bool mod);
182
183protected slots:
184 void OnDescEdited();
185 void OnNameEdited(const QString& text);
186 void OnBitRangeEdited(const QString& string);
187 void OnValueActivated(int row, int column);
188 void OnValueChanged(int row, int column);
189
190protected:
191 void CreateNewRow(int row);
192 void FillRow(int row, const soc_reg_field_value_t& val);
193 void UpdateWarning(int row);
194 void UpdateDelegates();
195
196 enum
197 {
198 FieldValueDeleteType = QTableWidgetItem::UserType,
199 FieldValueNewType,
200 };
201
202 enum
203 {
204 FieldValueIconColumn = 0,
205 FieldValueNameColumn,
206 FieldValueValueColumn,
207 FieldValueDescColumn,
208 FieldValueNrColumns,
209 };
210
211 SocFieldRef m_ref;
212 QGroupBox *m_name_group;
213 QLineEdit *m_name_edit;
214 QGroupBox *m_bitrange_group;
215 QLineEdit *m_bitrange_edit;
216 QGroupBox *m_desc_group;
217 MyTextEditor *m_desc_edit;
218 QGroupBox *m_value_group;
219 QTableWidget *m_value_table;
220};
221
222class RegEdit : public QWidget, public DocumentTab
223{
224 Q_OBJECT
225public:
226 RegEdit(Backend *backend, QWidget *parent = 0);
227 ~RegEdit();
228 virtual bool Quit();
229
230signals:
231 void OnModified(bool mod);
232
233protected slots:
234 void OnSocItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
235 void OnSocItemActivated(QTreeWidgetItem *current, int column);
236 void OnOpen();
237 void OnSave();
238 void OnSaveAs();
239 void OnSocModified(bool modified);
240 void OnNew();
241
242protected:
243 void LoadSocFile(const QString& filename);
244 void UpdateSocFile();
245 void FillSocTree();
246 void FillSocTreeItem(QTreeWidgetItem *_item);
247 void FillDevTreeItem(QTreeWidgetItem *_item);
248 void FillRegTreeItem(QTreeWidgetItem *_item);
249 void SetPanel(QWidget *panel);
250 void DisplaySoc(SocRef ref);
251 void DisplayDev(SocDevRef ref);
252 void DisplayReg(SocRegRef ref);
253 void DisplayField(SocFieldRef ref);
254 bool CloseSoc();
255 bool SaveSoc();
256 bool SaveSocAs();
257 bool SaveSocFile(const QString& filename);
258 bool GetFilename(QString& filename, bool save);
259 void SetModified(bool add, bool mod);
260 void FixupEmptyItem(QTreeWidgetItem *item);
261 void MakeItalic(QTreeWidgetItem *item, bool it);
262 void AddDevice(QTreeWidgetItem *item);
263 void AddRegister(QTreeWidgetItem *_item);
264 void UpdateName(QTreeWidgetItem *current);
265 void AddField(QTreeWidgetItem *_item);
266 void CreateNewDeviceItem(QTreeWidgetItem *parent);
267 void CreateNewRegisterItem(QTreeWidgetItem *parent);
268 void CreateNewFieldItem(QTreeWidgetItem *parent);
269
270 QGroupBox *m_file_group;
271 QToolButton *m_file_open;
272 QToolButton *m_file_save;
273 QLineEdit *m_file_edit;
274 QSplitter *m_splitter;
275 QTreeWidget *m_soc_tree;
276 Backend *m_backend;
277 bool m_modified;
278 SocFile m_cur_socfile;
279 QWidget *m_right_panel;
280};
281
282#endif /* REGEDIT_H */
diff --git a/utils/regtools/qeditor/regtab.cpp b/utils/regtools/qeditor/regtab.cpp
index 4cd4e7b283..568d859c0e 100644
--- a/utils/regtools/qeditor/regtab.cpp
+++ b/utils/regtools/qeditor/regtab.cpp
@@ -1,406 +1,75 @@
1#include "regtab.h" 1#include "regtab.h"
2 2
3#include <QSplitter>
4#include <QVBoxLayout>
5#include <QAbstractListModel>
6#include <QMessageBox>
7#include <QSizePolicy> 3#include <QSizePolicy>
8#include <QHBoxLayout>
9#include <QStringBuilder> 4#include <QStringBuilder>
10#include <QLabel>
11#include <QGridLayout>
12#include <QTableWidget>
13#include <QHeaderView>
14#include <QFileDialog> 5#include <QFileDialog>
15#include <QDebug> 6#include <QDebug>
16#include <QStyle> 7#include <QStyle>
17#include "backend.h" 8#include "backend.h"
18#include "analyser.h" 9#include "analyser.h"
10#include "regdisplaypanel.h"
19 11
20/** 12namespace
21 * SocFieldValidator
22 */
23
24SocFieldValidator::SocFieldValidator(QObject *parent)
25 :QValidator(parent)
26{
27 m_field.first_bit = 0;
28 m_field.last_bit = 31;
29}
30
31SocFieldValidator::SocFieldValidator(const soc_reg_field_t& field, QObject *parent)
32 :QValidator(parent), m_field(field)
33{
34}
35
36void SocFieldValidator::fixup(QString& input) const
37{
38 input = input.trimmed();
39}
40
41QValidator::State SocFieldValidator::validate(QString& input, int& pos) const
42{
43 (void) pos;
44 soc_word_t val;
45 State state = parse(input, val);
46 return state;
47}
48
49QValidator::State SocFieldValidator::parse(const QString& input, soc_word_t& val) const
50{
51 // the empty string is all alwats intermediate
52 if(input.size() == 0)
53 return Intermediate;
54 // first check named values
55 State state = Invalid;
56 foreach(const soc_reg_field_value_t& value, m_field.value)
57 {
58 QString name = QString::fromLocal8Bit(value.name.c_str());
59 // cannot be a substring if too long or empty
60 if(input.size() > name.size())
61 continue;
62 // check equal string
63 if(input == name)
64 {
65 state = Acceptable;
66 val = value.value;
67 break;
68 }
69 // check substring
70 if(name.startsWith(input))
71 state = Intermediate;
72 }
73 // early return for exact match
74 if(state == Acceptable)
75 return state;
76 // do a few special cases for convenience
77 if(input.compare("0x", Qt::CaseInsensitive) == 0 ||
78 input.compare("0b", Qt::CaseInsensitive) == 0)
79 return Intermediate;
80 // try by parsing
81 unsigned basis, pos;
82 if(input.size() >= 2 && input.startsWith("0x", Qt::CaseInsensitive))
83 {
84 basis = 16;
85 pos = 2;
86 }
87 else if(input.size() >= 2 && input.startsWith("0b", Qt::CaseInsensitive))
88 {
89 basis = 2;
90 pos = 2;
91 }
92 else if(input.size() >= 2 && input.startsWith("0"))
93 {
94 basis = 8;
95 pos = 1;
96 }
97 else
98 {
99 basis = 10;
100 pos = 0;
101 }
102 bool ok = false;
103 unsigned long v = input.mid(pos).toULong(&ok, basis);
104 // if not ok, return result of name parsing
105 if(!ok)
106 return state;
107 // if ok, check if it fits in the number of bits
108 unsigned nr_bits = m_field.last_bit - m_field.first_bit + 1;
109 unsigned long max = nr_bits == 32 ? 0xffffffff : (1 << nr_bits) - 1;
110 if(v <= max)
111 {
112 val = v;
113 return Acceptable;
114 }
115
116 return state;
117}
118
119/**
120 * RegLineEdit
121 */
122RegLineEdit::RegLineEdit(QWidget *parent)
123 :QWidget(parent)
124{ 13{
125 m_layout = new QHBoxLayout(this);
126 m_button = new QToolButton(this);
127 m_button->setCursor(Qt::ArrowCursor);
128 m_button->setStyleSheet("QToolButton { font-weight: bold; color: white; background: black; }");
129 m_button->setPopupMode(QToolButton::InstantPopup);
130 m_edit = new QLineEdit(this);
131 m_layout->addWidget(m_button);
132 m_layout->addWidget(m_edit);
133 m_menu = new QMenu(this);
134 connect(m_menu->addAction("Write"), SIGNAL(triggered()), this, SLOT(OnWriteAct()));
135 connect(m_menu->addAction("Set"), SIGNAL(triggered()), this, SLOT(OnSetAct()));
136 connect(m_menu->addAction("Clear"), SIGNAL(triggered()), this, SLOT(OnClearAct()));
137 connect(m_menu->addAction("Toggle"), SIGNAL(triggered()), this, SLOT(OnToggleAct()));
138 EnableSCT(false);
139 SetReadOnly(false);
140 ShowMode(true);
141 SetMode(Write);
142}
143 14
144void RegLineEdit::SetReadOnly(bool ro) 15enum
145{ 16{
146 m_edit->setReadOnly(ro); 17 RegTreeDevType = QTreeWidgetItem::UserType,
147 m_readonly = ro; 18 RegTreeRegType
148 ShowMode(!ro); 19};
149}
150 20
151void RegLineEdit::EnableSCT(bool en) 21class DevTreeItem : public QTreeWidgetItem
152{ 22{
153 m_has_sct = en; 23public:
154 if(!m_has_sct) 24 DevTreeItem(const QString& string, const SocDevRef& ref)
155 { 25 :QTreeWidgetItem(QStringList(string), RegTreeDevType), m_ref(ref) {}
156 m_button->setMenu(0);
157 SetMode(Write);
158 }
159 else
160 m_button->setMenu(m_menu);
161}
162
163RegLineEdit::~RegLineEdit()
164{
165}
166 26
167QLineEdit *RegLineEdit::GetLineEdit() 27 const SocDevRef& GetRef() { return m_ref; }
168{ 28private:
169 return m_edit; 29 SocDevRef m_ref;
170} 30};
171 31
172void RegLineEdit::ShowMode(bool show) 32class RegTreeItem : public QTreeWidgetItem
173{ 33{
174 if(show) 34public:
175 m_button->show(); 35 RegTreeItem(const QString& string, const SocRegRef& ref)
176 else 36 :QTreeWidgetItem(QStringList(string), RegTreeRegType), m_ref(ref) {}
177 m_button->hide();
178}
179 37
180void RegLineEdit::OnWriteAct() 38 const SocRegRef& GetRef() { return m_ref; }
181{ 39private:
182 SetMode(Write); 40 SocRegRef m_ref;
183} 41};
184
185void RegLineEdit::OnSetAct()
186{
187 SetMode(Set);
188}
189
190void RegLineEdit::OnClearAct()
191{
192 SetMode(Clear);
193}
194
195void RegLineEdit::OnToggleAct()
196{
197 SetMode(Toggle);
198}
199
200void RegLineEdit::SetMode(EditMode mode)
201{
202 m_mode = mode;
203 switch(m_mode)
204 {
205 case Write: m_button->setText("WR"); break;
206 case Set: m_button->setText("SET"); break;
207 case Clear: m_button->setText("CLR"); break;
208 case Toggle: m_button->setText("TOG"); break;
209 default: break;
210 }
211}
212 42
213RegLineEdit::EditMode RegLineEdit::GetMode()
214{
215 return m_mode;
216} 43}
217 44
218/** 45/**
219 * RegDisplayPanel 46 * EmptyRegTabPanel
220 */ 47 */
221 48EmptyRegTabPanel::EmptyRegTabPanel(QWidget *parent)
222RegDisplayPanel::RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg_ref) 49 :QWidget(parent)
223 :QGroupBox(parent), m_io_backend(io_backend), m_reg(reg_ref)
224{ 50{
225 bool read_only = m_io_backend->IsReadOnly(); 51 QVBoxLayout *l = new QVBoxLayout;
226 52 l->addStretch();
227 QVBoxLayout *right_layout = new QVBoxLayout; 53 setLayout(l);
228
229 const soc_dev_addr_t& dev_addr = m_reg.GetDevAddr();
230 const soc_reg_t& reg = m_reg.GetReg();
231 const soc_reg_addr_t& reg_addr = m_reg.GetRegAddr();
232
233 QString reg_name;
234 reg_name.sprintf("HW_%s_%s", dev_addr.name.c_str(), reg_addr.name.c_str());
235 QStringList names;
236 QVector< soc_addr_t > addresses;
237 names.append(reg_name);
238 addresses.append(reg_addr.addr);
239 if(reg.flags & REG_HAS_SCT)
240 {
241 names.append(reg_name + "_SET");
242 names.append(reg_name + "_CLR");
243 names.append(reg_name + "_TOG");
244 addresses.append(reg_addr.addr + 4);
245 addresses.append(reg_addr.addr + 8);
246 addresses.append(reg_addr.addr + 12);
247 }
248
249 QString str;
250 str += "<table align=left>";
251 for(int i = 0; i < names.size(); i++)
252 str += "<tr><td><b>" + names[i] + "</b></td></tr>";
253 str += "</table>";
254 QLabel *label_names = new QLabel;
255 label_names->setTextFormat(Qt::RichText);
256 label_names->setText(str);
257
258 QString str_addr;
259 str_addr += "<table align=left>";
260 for(int i = 0; i < names.size(); i++)
261 str_addr += "<tr><td><b>" + QString().sprintf("0x%03x", addresses[i]) + "</b></td></tr>";
262 str_addr += "</table>";
263 QLabel *label_addr = new QLabel;
264 label_addr->setTextFormat(Qt::RichText);
265 label_addr->setText(str_addr);
266
267 QHBoxLayout *top_layout = new QHBoxLayout;
268 top_layout->addStretch();
269 top_layout->addWidget(label_names);
270 top_layout->addWidget(label_addr);
271 top_layout->addStretch();
272
273 soc_word_t value;
274 BackendHelper helper(m_io_backend, m_reg);
275 bool has_value = helper.ReadRegister(dev_addr.name.c_str(), reg_addr.name.c_str(), value);
276
277 QHBoxLayout *raw_val_layout = 0;
278 if(has_value)
279 {
280 QLabel *raw_val_name = new QLabel;
281 raw_val_name->setText("Raw value:");
282 m_raw_val_edit = new RegLineEdit;
283 m_raw_val_edit->SetReadOnly(read_only);
284 m_raw_val_edit->GetLineEdit()->setText(QString().sprintf("0x%08x", value));
285 m_raw_val_edit->GetLineEdit()->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
286 m_raw_val_edit->GetLineEdit()->setValidator(new SocFieldValidator(m_raw_val_edit));
287 m_raw_val_edit->EnableSCT(!!(reg.flags & REG_HAS_SCT));
288 connect(m_raw_val_edit->GetLineEdit(), SIGNAL(returnPressed()), this, SLOT(OnRawRegValueReturnPressed()));
289 raw_val_layout = new QHBoxLayout;
290 raw_val_layout->addStretch();
291 raw_val_layout->addWidget(raw_val_name);
292 raw_val_layout->addWidget(m_raw_val_edit);
293 raw_val_layout->addStretch();
294 }
295 else
296 m_raw_val_edit = 0;
297
298 QTableWidget *value_table = new QTableWidget;
299 value_table->setRowCount(reg.field.size());
300 value_table->setColumnCount(4);
301 int row = 0;
302 foreach(const soc_reg_field_t& field, reg.field)
303 {
304 QString bits_str;
305 if(field.first_bit == field.last_bit)
306 bits_str.sprintf("%d", field.first_bit);
307 else
308 bits_str.sprintf("%d:%d", field.last_bit, field.first_bit);
309 QTableWidgetItem *item = new QTableWidgetItem(bits_str);
310 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
311 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
312 value_table->setItem(row, 0, item);
313 item = new QTableWidgetItem(QString(field.name.c_str()));
314 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
315 value_table->setItem(row, 1, item);
316 item = new QTableWidgetItem();
317 if(has_value)
318 {
319 soc_word_t v = (value & field.bitmask()) >> field.first_bit;
320 QString value_name;
321 foreach(const soc_reg_field_value_t& rval, field.value)
322 if(v == rval.value)
323 value_name = rval.name.c_str();
324 const char *fmt = "%lu";
325 // heuristic
326 if((field.last_bit - field.first_bit + 1) > 16)
327 fmt = "0x%lx";
328 item->setText(QString().sprintf(fmt, (unsigned long)v));
329 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
330
331 if(value_name.size() != 0)
332 {
333 QTableWidgetItem *t = new QTableWidgetItem(value_name);
334 t->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
335 t->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
336 value_table->setItem(row, 3, t);
337 }
338 }
339 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
340 value_table->setItem(row, 2, item);
341 row++;
342 }
343 value_table->setHorizontalHeaderItem(0, new QTableWidgetItem("Bits"));
344 value_table->setHorizontalHeaderItem(1, new QTableWidgetItem("Name"));
345 value_table->setHorizontalHeaderItem(2, new QTableWidgetItem("Value"));
346 value_table->setHorizontalHeaderItem(3, new QTableWidgetItem("Meaning"));
347 value_table->verticalHeader()->setVisible(false);
348 value_table->resizeColumnsToContents();
349 value_table->horizontalHeader()->setStretchLastSection(true);
350 value_table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
351
352 right_layout->addLayout(top_layout);
353 if(raw_val_layout)
354 right_layout->addLayout(raw_val_layout);
355 //right_layout->addWidget(bits_label);
356 right_layout->addWidget(value_table);
357 //right_layout->addStretch();
358
359 setTitle("Register Description");
360 setLayout(right_layout);
361 AllowWrite(false);
362} 54}
363 55
364void RegDisplayPanel::AllowWrite(bool en) 56void EmptyRegTabPanel::AllowWrite(bool en)
365{ 57{
366 m_allow_write = en; 58 Q_UNUSED(en);
367 if(m_raw_val_edit)
368 m_raw_val_edit->SetReadOnly(m_io_backend->IsReadOnly() || !m_allow_write);
369} 59}
370 60
371IoBackend::WriteMode RegDisplayPanel::EditModeToWriteMode(RegLineEdit::EditMode mode) 61QWidget *EmptyRegTabPanel::GetWidget()
372{ 62{
373 switch(mode) 63 return this;
374 {
375 case RegLineEdit::Write: return IoBackend::Write;
376 case RegLineEdit::Set: return IoBackend::Set;
377 case RegLineEdit::Clear: return IoBackend::Clear;
378 case RegLineEdit::Toggle: return IoBackend::Toggle;
379 default: return IoBackend::Write;
380 }
381} 64}
382 65
383void RegDisplayPanel::OnRawRegValueReturnPressed()
384{
385 soc_word_t val;
386 QLineEdit *edit = m_raw_val_edit->GetLineEdit();
387 const SocFieldValidator *validator = dynamic_cast< const SocFieldValidator *>(edit->validator());
388 QValidator::State state = validator->parse(edit->text(), val);
389 if(state != QValidator::Acceptable)
390 return;
391 IoBackend::WriteMode mode = EditModeToWriteMode(m_raw_val_edit->GetMode());
392 BackendHelper helper(m_io_backend, m_reg);
393 helper.WriteRegister(m_reg.GetDevAddr().name.c_str(), m_reg.GetRegAddr().name.c_str(),
394 val, mode);
395 // FIXME: we should notify the UI to read value back because it has changed
396}
397 66
398/** 67/**
399 * RegTab 68 * RegTab
400 */ 69 */
401 70
402RegTab::RegTab(Backend *backend) 71RegTab::RegTab(Backend *backend, QWidget *parent)
403 :m_backend(backend) 72 :QSplitter(parent), m_backend(backend)
404{ 73{
405 QWidget *left = new QWidget; 74 QWidget *left = new QWidget;
406 this->addWidget(left); 75 this->addWidget(left);
@@ -432,7 +101,7 @@ RegTab::RegTab(Backend *backend)
432 QGroupBox *data_sel_group = new QGroupBox("Data selection"); 101 QGroupBox *data_sel_group = new QGroupBox("Data selection");
433 QHBoxLayout *data_sel_layout = new QHBoxLayout; 102 QHBoxLayout *data_sel_layout = new QHBoxLayout;
434 m_data_selector = new QComboBox; 103 m_data_selector = new QComboBox;
435 m_data_selector->addItem(QIcon::fromTheme("face-sad"), "None", QVariant(DataSelNothing)); 104 m_data_selector->addItem(QIcon::fromTheme("text-x-generic"), "Explore", QVariant(DataSelNothing));
436 m_data_selector->addItem(QIcon::fromTheme("document-open"), "File...", QVariant(DataSelFile)); 105 m_data_selector->addItem(QIcon::fromTheme("document-open"), "File...", QVariant(DataSelFile));
437#ifdef HAVE_HWSTUB 106#ifdef HAVE_HWSTUB
438 m_data_selector->addItem(QIcon::fromTheme("multimedia-player"), "Device...", QVariant(DataSelDevice)); 107 m_data_selector->addItem(QIcon::fromTheme("multimedia-player"), "Device...", QVariant(DataSelDevice));
@@ -446,7 +115,8 @@ RegTab::RegTab(Backend *backend)
446 data_sel_reload->setIcon(QIcon::fromTheme("view-refresh")); 115 data_sel_reload->setIcon(QIcon::fromTheme("view-refresh"));
447 data_sel_reload->setToolTip("Reload data"); 116 data_sel_reload->setToolTip("Reload data");
448 data_sel_layout->addWidget(m_data_selector); 117 data_sel_layout->addWidget(m_data_selector);
449 data_sel_layout->addWidget(m_data_sel_edit); 118 data_sel_layout->addWidget(m_data_sel_edit, 1);
119 data_sel_layout->addStretch(0);
450#ifdef HAVE_HWSTUB 120#ifdef HAVE_HWSTUB
451 m_dev_selector = new QComboBox; 121 m_dev_selector = new QComboBox;
452 data_sel_layout->addWidget(m_dev_selector, 1); 122 data_sel_layout->addWidget(m_dev_selector, 1);
@@ -457,12 +127,9 @@ RegTab::RegTab(Backend *backend)
457 data_sel_group->setLayout(data_sel_layout); 127 data_sel_group->setLayout(data_sel_layout);
458 m_data_soc_label->setFrameStyle(QFrame::StyledPanel | QFrame::Raised); 128 m_data_soc_label->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
459 129
460 m_right_panel->addWidget(data_sel_group); 130 m_right_panel->addWidget(data_sel_group, 0);
461 m_right_content = new QWidget; 131 m_right_content = 0;
462 QVBoxLayout *l = new QVBoxLayout; 132 SetPanel(new EmptyRegTabPanel);
463 l->addStretch();
464 m_right_content->setLayout(l);
465 m_right_panel->addWidget(m_right_content);
466 QWidget *w = new QWidget; 133 QWidget *w = new QWidget;
467 w->setLayout(m_right_panel); 134 w->setLayout(m_right_panel);
468 this->addWidget(w); 135 this->addWidget(w);
@@ -470,21 +137,17 @@ RegTab::RegTab(Backend *backend)
470 137
471 m_io_backend = m_backend->CreateDummyIoBackend(); 138 m_io_backend = m_backend->CreateDummyIoBackend();
472 139
473 connect(m_soc_selector, SIGNAL(currentIndexChanged(const QString&)), 140 connect(m_soc_selector, SIGNAL(currentIndexChanged(int)),
474 this, SLOT(OnSocChanged(const QString&))); 141 this, SLOT(OnSocChanged(int)));
475 connect(m_backend, SIGNAL(OnSocListChanged()), this, SLOT(OnSocListChanged())); 142 connect(m_backend, SIGNAL(OnSocListChanged()), this, SLOT(OnSocListChanged()));
476 connect(m_reg_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), 143 connect(m_reg_tree, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)),
477 this, SLOT(OnRegItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); 144 this, SLOT(OnRegItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)));
478 connect(m_reg_tree, SIGNAL(itemClicked(QTreeWidgetItem *, int)), this,
479 SLOT(OnRegItemClicked(QTreeWidgetItem *, int)));
480 connect(m_data_selector, SIGNAL(activated(int)), 145 connect(m_data_selector, SIGNAL(activated(int)),
481 this, SLOT(OnDataSelChanged(int))); 146 this, SLOT(OnDataSelChanged(int)));
482 connect(m_data_soc_label, SIGNAL(linkActivated(const QString&)), this, 147 connect(m_data_soc_label, SIGNAL(linkActivated(const QString&)), this,
483 SLOT(OnDataSocActivated(const QString&))); 148 SLOT(OnDataSocActivated(const QString&)));
484 connect(m_analysers_list, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)), 149 connect(m_analysers_list, SIGNAL(currentItemChanged(QListWidgetItem *, QListWidgetItem *)),
485 this, SLOT(OnAnalyserChanged(QListWidgetItem *, QListWidgetItem *))); 150 this, SLOT(OnAnalyserChanged(QListWidgetItem *, QListWidgetItem *)));
486 connect(m_analysers_list, SIGNAL(itemClicked(QListWidgetItem *)), this,
487 SLOT(OnAnalyserClicked(QListWidgetItem *)));
488#ifdef HAVE_HWSTUB 151#ifdef HAVE_HWSTUB
489 connect(m_dev_selector, SIGNAL(currentIndexChanged(int)), 152 connect(m_dev_selector, SIGNAL(currentIndexChanged(int)),
490 this, SLOT(OnDevChanged(int))); 153 this, SLOT(OnDevChanged(int)));
@@ -492,14 +155,22 @@ RegTab::RegTab(Backend *backend)
492 connect(m_readonly_check, SIGNAL(clicked(bool)), this, SLOT(OnReadOnlyClicked(bool))); 155 connect(m_readonly_check, SIGNAL(clicked(bool)), this, SLOT(OnReadOnlyClicked(bool)));
493 156
494 OnSocListChanged(); 157 OnSocListChanged();
495 OnDataSelChanged(DataSelNothing); 158 OnDataSelChanged(0);
496} 159}
497 160
498RegTab::~RegTab() 161RegTab::~RegTab()
499{ 162{
163#ifdef HAVE_HWSTUB
164 ClearDevList();
165#endif
500 delete m_io_backend; 166 delete m_io_backend;
501} 167}
502 168
169bool RegTab::Quit()
170{
171 return true;
172}
173
503void RegTab::SetDataSocName(const QString& socname) 174void RegTab::SetDataSocName(const QString& socname)
504{ 175{
505 if(socname.size() != 0) 176 if(socname.size() != 0)
@@ -533,9 +204,10 @@ void RegTab::OnDataSelChanged(int index)
533#ifdef HAVE_HWSTUB 204#ifdef HAVE_HWSTUB
534 m_dev_selector->hide(); 205 m_dev_selector->hide();
535#endif 206#endif
207 m_readonly_check->show();
536 QFileDialog *fd = new QFileDialog(m_data_selector); 208 QFileDialog *fd = new QFileDialog(m_data_selector);
537 fd->setFilter("Textual files (*.txt);;All files (*)"); 209 fd->setFilter("Textual files (*.txt);;All files (*)");
538 fd->setDirectory(Settings::Get()->value("regtab/loaddatadir", QDir::currentPath()).toString()); 210 fd->setDirectory(Settings::Get()->value("loaddatadir", QDir::currentPath()).toString());
539 if(fd->exec()) 211 if(fd->exec())
540 { 212 {
541 QStringList filenames = fd->selectedFiles(); 213 QStringList filenames = fd->selectedFiles();
@@ -545,13 +217,14 @@ void RegTab::OnDataSelChanged(int index)
545 SetDataSocName(m_io_backend->GetSocName()); 217 SetDataSocName(m_io_backend->GetSocName());
546 OnDataSocActivated(m_io_backend->GetSocName()); 218 OnDataSocActivated(m_io_backend->GetSocName());
547 } 219 }
548 Settings::Get()->setValue("regtab/loaddatadir", fd->directory().absolutePath()); 220 Settings::Get()->setValue("loaddatadir", fd->directory().absolutePath());
549 SetReadOnlyIndicator(); 221 SetReadOnlyIndicator();
550 } 222 }
551#ifdef HAVE_HWSTUB 223#ifdef HAVE_HWSTUB
552 else if(var == DataSelDevice) 224 else if(var == DataSelDevice)
553 { 225 {
554 m_data_sel_edit->hide(); 226 m_data_sel_edit->hide();
227 m_readonly_check->show();
555 m_dev_selector->show(); 228 m_dev_selector->show();
556 OnDevListChanged(); 229 OnDevListChanged();
557 } 230 }
@@ -562,13 +235,31 @@ void RegTab::OnDataSelChanged(int index)
562#ifdef HAVE_HWSTUB 235#ifdef HAVE_HWSTUB
563 m_dev_selector->hide(); 236 m_dev_selector->hide();
564#endif 237#endif
238 m_readonly_check->hide();
239
565 delete m_io_backend; 240 delete m_io_backend;
566 m_io_backend = m_backend->CreateDummyIoBackend(); 241 m_io_backend = m_backend->CreateDummyIoBackend();
242 m_readonly_check->setCheckState(Qt::Checked);
567 SetDataSocName(""); 243 SetDataSocName("");
244 UpdateSocFilename();
568 } 245 }
569 OnDataChanged(); 246 OnDataChanged();
570} 247}
571 248
249void RegTab::UpdateSocFilename()
250{
251 int index = m_data_selector->currentIndex();
252 if(index == -1)
253 return;
254 if(m_data_selector->itemData(index) != DataSelNothing)
255 return;
256 index = m_soc_selector->currentIndex();
257 if(index == -1)
258 return;
259 SocRef ref = m_soc_selector->itemData(index).value< SocRef >();
260 m_data_sel_edit->setText(ref.GetSocFile()->GetFilename());
261}
262
572void RegTab::SetReadOnlyIndicator() 263void RegTab::SetReadOnlyIndicator()
573{ 264{
574 if(m_io_backend->IsReadOnly()) 265 if(m_io_backend->IsReadOnly())
@@ -582,23 +273,30 @@ void RegTab::OnDataChanged()
582 273
583void RegTab::OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) 274void RegTab::OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
584{ 275{
585 (void) previous; 276 Q_UNUSED(previous);
586 OnRegItemClicked(current, 0); 277 OnRegItemClicked(current, 0);
587} 278}
588 279
589void RegTab::OnRegItemClicked(QTreeWidgetItem *current, int col) 280void RegTab::OnRegItemClicked(QTreeWidgetItem *current, int col)
590{ 281{
591 (void) col; 282 Q_UNUSED(col);
592 if(current == 0 || current->type() != RegTreeRegType) 283 if(current == 0)
593 return; 284 return;
594 RegTreeItem *item = dynamic_cast< RegTreeItem * >(current); 285 if(current->type() == RegTreeRegType)
595 286 {
596 DisplayRegister(item->GetRef()); 287 RegTreeItem *item = dynamic_cast< RegTreeItem * >(current);
288 DisplayRegister(item->GetRef());
289 }
290 else if(current->type() == RegTreeDevType)
291 {
292 DevTreeItem *item = dynamic_cast< DevTreeItem * >(current);
293 DisplayDevice(item->GetRef());
294 }
597} 295}
598 296
599void RegTab::OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous) 297void RegTab::OnAnalyserChanged(QListWidgetItem *current, QListWidgetItem *previous)
600{ 298{
601 (void) previous; 299 Q_UNUSED(previous);
602 OnAnalyserClicked(current); 300 OnAnalyserClicked(current);
603} 301}
604 302
@@ -606,33 +304,44 @@ void RegTab::OnAnalyserClicked(QListWidgetItem *current)
606{ 304{
607 if(current == 0) 305 if(current == 0)
608 return; 306 return;
609 delete m_right_content;
610 AnalyserFactory *ana = AnalyserFactory::GetAnalyserByName(current->text()); 307 AnalyserFactory *ana = AnalyserFactory::GetAnalyserByName(current->text());
611 m_right_content = ana->Create(m_cur_soc, m_io_backend)->GetWidget(); 308 SetPanel(ana->Create(m_cur_soc, m_io_backend));
612 m_right_panel->addWidget(m_right_content, 1);
613} 309}
614 310
615void RegTab::DisplayRegister(const SocRegRef& ref) 311void RegTab::DisplayRegister(const SocRegRef& ref)
616{ 312{
313 SetPanel(new RegDisplayPanel(this, m_io_backend, ref));
314}
315
316void RegTab::DisplayDevice(const SocDevRef& ref)
317{
318 SetPanel(new DevDisplayPanel(this, ref));
319}
320
321void RegTab::SetPanel(RegTabPanel *panel)
322{
617 delete m_right_content; 323 delete m_right_content;
618 RegDisplayPanel *panel = new RegDisplayPanel(this, m_io_backend, ref);
619 panel->AllowWrite(m_readonly_check->checkState() == Qt::Unchecked);
620 m_right_content = panel; 324 m_right_content = panel;
621 m_right_panel->addWidget(m_right_content); 325 m_right_content->AllowWrite(m_readonly_check->checkState() == Qt::Unchecked);
326 m_right_panel->addWidget(m_right_content->GetWidget(), 1);
622} 327}
623 328
624void RegTab::OnSocListChanged() 329void RegTab::OnSocListChanged()
625{ 330{
626 m_soc_selector->clear(); 331 m_soc_selector->clear();
627 QStringList socs = m_backend->GetSocNameList(); 332 QList< SocRef > socs = m_backend->GetSocList();
628 for(int i = 0; i < socs.size(); i++) 333 for(int i = 0; i < socs.size(); i++)
629 m_soc_selector->addItem(socs[i]); 334 {
335 QVariant v;
336 v.setValue(socs[i]);
337 m_soc_selector->addItem(QString::fromStdString(socs[i].GetSoc().name), v);
338 }
630} 339}
631 340
632#ifdef HAVE_HWSTUB 341#ifdef HAVE_HWSTUB
633void RegTab::OnDevListChanged() 342void RegTab::OnDevListChanged()
634{ 343{
635 m_dev_selector->clear(); 344 ClearDevList();
636 QList< HWStubDevice* > list = m_hwstub_helper.GetDevList(); 345 QList< HWStubDevice* > list = m_hwstub_helper.GetDevList();
637 foreach(HWStubDevice *dev, list) 346 foreach(HWStubDevice *dev, list)
638 { 347 {
@@ -659,10 +368,21 @@ void RegTab::OnDevChanged(int index)
659 OnDataSocActivated(m_io_backend->GetSocName()); 368 OnDataSocActivated(m_io_backend->GetSocName());
660 OnDataChanged(); 369 OnDataChanged();
661} 370}
371
372void RegTab::ClearDevList()
373{
374 while(m_dev_selector->count() > 0)
375 {
376 HWStubDevice *dev = reinterpret_cast< HWStubDevice* >(m_dev_selector->itemData(0).value< void* >());
377 delete dev;
378 m_dev_selector->removeItem(0);
379 }
380}
662#endif 381#endif
663 382
664void RegTab::FillDevSubTree(DevTreeItem *item) 383void RegTab::FillDevSubTree(QTreeWidgetItem *_item)
665{ 384{
385 DevTreeItem *item = dynamic_cast< DevTreeItem* >(_item);
666 const soc_dev_t& dev = item->GetRef().GetDev(); 386 const soc_dev_t& dev = item->GetRef().GetDev();
667 for(size_t i = 0; i < dev.reg.size(); i++) 387 for(size_t i = 0; i < dev.reg.size(); i++)
668 { 388 {
@@ -697,23 +417,21 @@ void RegTab::FillAnalyserList()
697 m_analysers_list->addItems(AnalyserFactory::GetAnalysersForSoc(m_cur_soc.GetSoc().name.c_str())); 417 m_analysers_list->addItems(AnalyserFactory::GetAnalysersForSoc(m_cur_soc.GetSoc().name.c_str()));
698} 418}
699 419
700void RegTab::OnSocChanged(const QString& soc) 420void RegTab::OnSocChanged(int index)
701{ 421{
702 m_reg_tree->clear(); 422 if(index == -1)
703 if(!m_backend->GetSocByName(soc, m_cur_soc))
704 return; 423 return;
424 m_reg_tree->clear();
425 m_cur_soc = m_soc_selector->itemData(index).value< SocRef >();
705 FillRegTree(); 426 FillRegTree();
706 FillAnalyserList(); 427 FillAnalyserList();
428 UpdateSocFilename();
707} 429}
708 430
709void RegTab::OnReadOnlyClicked(bool checked) 431void RegTab::OnReadOnlyClicked(bool checked)
710{ 432{
711 if(m_io_backend->IsReadOnly()) 433 if(m_io_backend->IsReadOnly())
712 return SetReadOnlyIndicator(); 434 return SetReadOnlyIndicator();
713 if(m_right_content == 0) 435 m_right_content->AllowWrite(!checked);
714 return; 436 UpdateSocFilename();
715 RegDisplayPanel *panel = dynamic_cast< RegDisplayPanel* >(m_right_content);
716 if(panel == 0)
717 return;
718 panel->AllowWrite(!checked);
719} 437}
diff --git a/utils/regtools/qeditor/regtab.h b/utils/regtools/qeditor/regtab.h
index 9fa1437119..78a10ba379 100644
--- a/utils/regtools/qeditor/regtab.h
+++ b/utils/regtools/qeditor/regtab.h
@@ -2,7 +2,6 @@
2#define REGTAB_H 2#define REGTAB_H
3 3
4#include <QComboBox> 4#include <QComboBox>
5#include <QEvent>
6#include <QTreeWidget> 5#include <QTreeWidget>
7#include <QVBoxLayout> 6#include <QVBoxLayout>
8#include <QTabWidget> 7#include <QTabWidget>
@@ -11,118 +10,41 @@
11#include <QPushButton> 10#include <QPushButton>
12#include <QLabel> 11#include <QLabel>
13#include <QListWidget> 12#include <QListWidget>
14#include <QValidator>
15#include <QGroupBox> 13#include <QGroupBox>
16#include <QToolButton> 14#include <QToolButton>
17#include <QMenu> 15#include <QMenu>
18#include <QCheckBox> 16#include <QCheckBox>
19#include <soc_desc.hpp>
20#include "backend.h" 17#include "backend.h"
21#include "settings.h" 18#include "settings.h"
19#include "mainwindow.h"
22 20
23enum 21class RegTabPanel
24{
25 RegTreeDevType = QTreeWidgetItem::UserType,
26 RegTreeRegType
27};
28
29class DevTreeItem : public QTreeWidgetItem
30{
31public:
32 DevTreeItem(const QString& string, const SocDevRef& ref)
33 :QTreeWidgetItem(QStringList(string), RegTreeDevType), m_ref(ref) {}
34
35 const SocDevRef& GetRef() { return m_ref; }
36private:
37 SocDevRef m_ref;
38};
39
40class RegTreeItem : public QTreeWidgetItem
41{ 22{
42public: 23public:
43 RegTreeItem(const QString& string, const SocRegRef& ref) 24 RegTabPanel() {}
44 :QTreeWidgetItem(QStringList(string), RegTreeRegType), m_ref(ref) {} 25 virtual ~RegTabPanel() {}
45 26 virtual void AllowWrite(bool en) = 0;
46 const SocRegRef& GetRef() { return m_ref; } 27 virtual QWidget *GetWidget() = 0;
47private:
48 SocRegRef m_ref;
49}; 28};
50 29
51class SocFieldValidator : public QValidator 30class EmptyRegTabPanel : public QWidget, public RegTabPanel
52{ 31{
53 Q_OBJECT
54public: 32public:
55 SocFieldValidator(QObject *parent = 0); 33 EmptyRegTabPanel(QWidget *parent = 0);
56 SocFieldValidator(const soc_reg_field_t& field, QObject *parent = 0);
57
58 virtual void fixup(QString& input) const;
59 virtual State validate(QString& input, int& pos) const;
60 /* validate and return the interpreted value */
61 State parse(const QString& input, soc_word_t& val) const;
62
63protected:
64 soc_reg_field_t m_field;
65};
66
67class RegLineEdit : public QWidget
68{
69 Q_OBJECT
70public:
71 enum EditMode
72 {
73 Write, Set, Clear, Toggle
74 };
75
76 RegLineEdit(QWidget *parent = 0);
77 ~RegLineEdit();
78 void SetReadOnly(bool ro);
79 void EnableSCT(bool en);
80 void SetMode(EditMode mode);
81 EditMode GetMode();
82 QLineEdit *GetLineEdit();
83
84protected slots:
85 void OnWriteAct();
86 void OnSetAct();
87 void OnClearAct();
88 void OnToggleAct();
89protected:
90 void ShowMode(bool show);
91
92 QHBoxLayout *m_layout;
93 QToolButton *m_button;
94 QLineEdit *m_edit;
95 EditMode m_mode;
96 bool m_has_sct;
97 bool m_readonly;
98 QMenu *m_menu;
99};
100
101class RegDisplayPanel : public QGroupBox
102{
103 Q_OBJECT
104public:
105 RegDisplayPanel(QWidget *parent, IoBackend *io_backend, const SocRegRef& reg);
106 void AllowWrite(bool en); 34 void AllowWrite(bool en);
107 35 QWidget *GetWidget();
108protected:
109 IoBackend::WriteMode EditModeToWriteMode(RegLineEdit::EditMode mode);
110
111 IoBackend *m_io_backend;
112 const SocRegRef& m_reg;
113 bool m_allow_write;
114 RegLineEdit *m_raw_val_edit;
115
116private slots:
117 void OnRawRegValueReturnPressed();
118}; 36};
119 37
120class RegTab : public QSplitter 38class RegTab : public QSplitter, public DocumentTab
121{ 39{
122 Q_OBJECT 40 Q_OBJECT
123public: 41public:
124 RegTab(Backend *backend); 42 RegTab(Backend *backend, QWidget *parent = 0);
125 ~RegTab(); 43 ~RegTab();
44 virtual bool Quit();
45
46signals:
47 void OnModified(bool modified);
126 48
127protected: 49protected:
128 enum 50 enum
@@ -134,12 +56,16 @@ protected:
134 #endif 56 #endif
135 }; 57 };
136 58
137 void FillDevSubTree(DevTreeItem *item); 59 void FillDevSubTree(QTreeWidgetItem *item);
138 void FillRegTree(); 60 void FillRegTree();
139 void FillAnalyserList(); 61 void FillAnalyserList();
140 void UpdateSocList(); 62 void UpdateSocList();
141 void DisplayRegister(const SocRegRef& ref); 63 void DisplayRegister(const SocRegRef& ref);
64 void DisplayDevice(const SocDevRef& ref);
142 void SetDataSocName(const QString& socname); 65 void SetDataSocName(const QString& socname);
66 void SetPanel(RegTabPanel *panel);
67 void UpdateSocFilename();
68
143 QComboBox *m_soc_selector; 69 QComboBox *m_soc_selector;
144#ifdef HAVE_HWSTUB 70#ifdef HAVE_HWSTUB
145 QComboBox *m_dev_selector; 71 QComboBox *m_dev_selector;
@@ -149,7 +75,7 @@ protected:
149 QTreeWidget *m_reg_tree; 75 QTreeWidget *m_reg_tree;
150 SocRef m_cur_soc; 76 SocRef m_cur_soc;
151 QVBoxLayout *m_right_panel; 77 QVBoxLayout *m_right_panel;
152 QWidget *m_right_content; 78 RegTabPanel *m_right_content;
153 QLineEdit *m_data_sel_edit; 79 QLineEdit *m_data_sel_edit;
154 QCheckBox *m_readonly_check; 80 QCheckBox *m_readonly_check;
155 QLabel *m_data_soc_label; 81 QLabel *m_data_soc_label;
@@ -163,9 +89,10 @@ private slots:
163#ifdef HAVE_HWSTUB 89#ifdef HAVE_HWSTUB
164 void OnDevListChanged(); 90 void OnDevListChanged();
165 void OnDevChanged(int index); 91 void OnDevChanged(int index);
92 void ClearDevList();
166#endif 93#endif
167 void SetReadOnlyIndicator(); 94 void SetReadOnlyIndicator();
168 void OnSocChanged(const QString& text); 95 void OnSocChanged(int index);
169 void OnSocListChanged(); 96 void OnSocListChanged();
170 void OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous); 97 void OnRegItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous);
171 void OnRegItemClicked(QTreeWidgetItem *clicked, int col); 98 void OnRegItemClicked(QTreeWidgetItem *clicked, int col);
diff --git a/utils/regtools/qeditor/std_analysers.cpp b/utils/regtools/qeditor/std_analysers.cpp
index 2cc84cb488..5847e39f7d 100644
--- a/utils/regtools/qeditor/std_analysers.cpp
+++ b/utils/regtools/qeditor/std_analysers.cpp
@@ -23,6 +23,7 @@ ClockAnalyser::ClockAnalyser(const SocRef& soc, IoBackend *backend)
23 23
24ClockAnalyser::~ClockAnalyser() 24ClockAnalyser::~ClockAnalyser()
25{ 25{
26 delete m_group;
26} 27}
27 28
28QWidget *ClockAnalyser::GetWidget() 29QWidget *ClockAnalyser::GetWidget()
@@ -287,9 +288,9 @@ void ClockAnalyser::FillTree()
287 else 288 else
288 AddClock(ref_xtal, "clk_rtc32k", INVALID); 289 AddClock(ref_xtal, "clk_rtc32k", INVALID);
289 290
290 (void) clk_x; 291 Q_UNUSED(clk_x);
291 (void) clk_gpmi; 292 Q_UNUSED(clk_gpmi);
292 (void) clk_h; 293 Q_UNUSED(clk_h);
293 294
294 m_tree_widget->expandAll(); 295 m_tree_widget->expandAll();
295 m_tree_widget->resizeColumnToContents(0); 296 m_tree_widget->resizeColumnToContents(0);
@@ -334,6 +335,7 @@ EmiAnalyser::EmiAnalyser(const SocRef& soc, IoBackend *backend)
334 335
335EmiAnalyser::~EmiAnalyser() 336EmiAnalyser::~EmiAnalyser()
336{ 337{
338 delete m_group;
337} 339}
338 340
339QWidget *EmiAnalyser::GetWidget() 341QWidget *EmiAnalyser::GetWidget()
@@ -671,6 +673,7 @@ PinAnalyser::PinAnalyser(const SocRef& soc, IoBackend *backend)
671 673
672PinAnalyser::~PinAnalyser() 674PinAnalyser::~PinAnalyser()
673{ 675{
676 delete m_group;
674} 677}
675 678
676QWidget *PinAnalyser::GetWidget() 679QWidget *PinAnalyser::GetWidget()
diff --git a/utils/regtools/qeditor/std_analysers.h b/utils/regtools/qeditor/std_analysers.h
index aae8e40207..cca8b12b99 100644
--- a/utils/regtools/qeditor/std_analysers.h
+++ b/utils/regtools/qeditor/std_analysers.h
@@ -21,7 +21,6 @@
21 21
22class ClockAnalyser : public Analyser 22class ClockAnalyser : public Analyser
23{ 23{
24 Q_OBJECT
25public: 24public:
26 ClockAnalyser(const SocRef& soc, IoBackend *backend); 25 ClockAnalyser(const SocRef& soc, IoBackend *backend);
27 virtual ~ClockAnalyser(); 26 virtual ~ClockAnalyser();
@@ -50,7 +49,7 @@ private:
50/** 49/**
51 * EMI analyser 50 * EMI analyser
52 */ 51 */
53class EmiAnalyser : public Analyser 52class EmiAnalyser : public QObject, public Analyser
54{ 53{
55 Q_OBJECT 54 Q_OBJECT
56public: 55public:
@@ -96,7 +95,6 @@ private:
96 */ 95 */
97class PinAnalyser : public Analyser 96class PinAnalyser : public Analyser
98{ 97{
99 Q_OBJECT
100public: 98public:
101 PinAnalyser(const SocRef& soc, IoBackend *backend); 99 PinAnalyser(const SocRef& soc, IoBackend *backend);
102 virtual ~PinAnalyser(); 100 virtual ~PinAnalyser();
diff --git a/utils/regtools/tester.cpp b/utils/regtools/tester.cpp
index 1fa21c6894..1beba5fe9b 100644
--- a/utils/regtools/tester.cpp
+++ b/utils/regtools/tester.cpp
@@ -21,77 +21,343 @@
21#include "soc_desc.hpp" 21#include "soc_desc.hpp"
22#include <stdio.h> 22#include <stdio.h>
23#include <stdlib.h> 23#include <stdlib.h>
24#include <map>
25#include <cstring>
24 26
25void print_value_desc(const soc_reg_field_value_t& value) 27template< typename T >
28bool build_map(const char *type, const std::vector< T >& vec,
29 std::map< std::string, size_t >& map)
26{ 30{
27 printf(" VALUE %s (%#x)\n", value.name.c_str(), value.value); 31 for(size_t i = 0; i < vec.size(); i++)
32 {
33 if(map.find(vec[i].name) != map.end())
34 {
35 printf("soc has duplicate %s '%s'\n", type, vec[i].name.c_str());
36 return false;
37 }
38 map[vec[i].name] = i;
39 }
40 return true;
28} 41}
29 42
30void print_field_desc(const soc_reg_field_t& field) 43template< typename T >
44bool build_map(const char *type, const std::vector< T >& a, const std::vector< T >& b,
45 std::vector< std::pair< size_t, size_t > >& m)
31{ 46{
32 printf(" FIELD %s (%d:%d)\n", field.name.c_str(), field.last_bit, 47 std::map< std::string, size_t > ma, mb;
33 field.first_bit); 48 if(!build_map(type, a, ma) || !build_map(type, b, mb))
34 for(size_t i = 0; i < field.value.size(); i++) 49 return false;
35 print_value_desc(field.value[i]); 50 std::map< std::string, size_t >::iterator it;
51 for(it = ma.begin(); it != ma.end(); ++it)
52 {
53 if(mb.find(it->first) == mb.end())
54 {
55 printf("%s '%s' exists in only one file\n", type, it->first.c_str());
56 return false;
57 }
58 m.push_back(std::make_pair(it->second, mb[it->first]));
59 }
60 for(it = mb.begin(); it != mb.end(); ++it)
61 {
62 if(ma.find(it->first) == ma.end())
63 {
64 printf("%s '%s' exists in only one file\n", type, it->first.c_str());
65 return false;
66 }
67 }
68 return true;
36} 69}
37 70
38std::string compute_sct(soc_reg_flags_t f) 71bool compare_value(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg,
72 const soc_reg_field_t& field, const soc_reg_field_value_t& a, const soc_reg_field_value_t& b)
39{ 73{
40 if(f & REG_HAS_SCT) return "SCT"; 74 if(a.value != b.value)
41 else return ""; 75 {
76 printf("register field value '%s.%s.%s.%s.%s' have different values\n", soc.name.c_str(),
77 dev.name.c_str(), reg.name.c_str(), field.name.c_str(), a.name.c_str());
78 return false;
79 }
80 if(a.desc != b.desc)
81 {
82 printf("register field value '%s.%s.%s.%s.%s' have different descriptions\n", soc.name.c_str(),
83 dev.name.c_str(), reg.name.c_str(), field.name.c_str(), a.name.c_str());
84 return false;
85 }
86 return true;
42} 87}
43 88
44void print_reg_addr_desc(const soc_reg_addr_t& reg) 89bool compare_field(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg,
90 const soc_reg_field_t& a, const soc_reg_field_t& b)
45{ 91{
46 printf(" ADDR %s %#x\n", reg.name.c_str(), reg.addr); 92 if(a.first_bit != b.first_bit || a.last_bit != b.last_bit)
93 {
94 printf("register address '%s.%s.%s.%s' have different bit ranges\n", soc.name.c_str(),
95 dev.name.c_str(), reg.name.c_str(), a.name.c_str());
96 return false;
97 }
98 if(a.desc != b.desc)
99 {
100 printf("register address '%s.%s.%s.%s' have different descriptions\n", soc.name.c_str(),
101 dev.name.c_str(), reg.name.c_str(), a.name.c_str());
102 return false;
103 }
104 /* values */
105 std::vector< std::pair< size_t, size_t > > map;
106 if(!build_map("field value", a.value, b.value, map))
107 return false;
108 for(size_t i = 0; i < map.size(); i++)
109 if(!compare_value(soc, dev, reg, a, a.value[map[i].first], b.value[map[i].second]))
110 return false;
111 return true;
47} 112}
48 113
49void print_reg_desc(const soc_reg_t& reg) 114bool compare_reg_addr(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& reg,
115 const soc_reg_addr_t& a, const soc_reg_addr_t& b)
50{ 116{
51 std::string sct = compute_sct(reg.flags); 117 if(a.addr != b.addr)
52 printf(" REG %s %s\n", reg.name.c_str(), sct.c_str()); 118 {
53 for(size_t i = 0; i < reg.addr.size(); i++) 119 printf("register address '%s.%s.%s.%s' have different values\n", soc.name.c_str(),
54 print_reg_addr_desc(reg.addr[i]); 120 dev.name.c_str(), reg.name.c_str(), a.name.c_str());
55 for(size_t i = 0; i < reg.field.size(); i++) 121 return false;
56 print_field_desc(reg.field[i]); 122 }
123 else
124 return true;
57} 125}
58 126
59void print_dev_addr_desc(const soc_dev_addr_t& dev) 127bool compare_reg(const soc_t& soc, const soc_dev_t& dev, const soc_reg_t& a,
128 const soc_reg_t& b)
60{ 129{
61 printf(" ADDR %s %#x\n", dev.name.c_str(), dev.addr); 130 if(a.desc != b.desc)
131 {
132 printf("register '%s.%s.%s' have different descriptions\n", soc.name.c_str(),
133 dev.name.c_str(), a.name.c_str());
134 return false;
135 }
136 if(a.flags != b.flags)
137 {
138 printf("device '%s.%s.%s' have different flags\n", soc.name.c_str(),
139 dev.name.c_str(), a.name.c_str());
140 return false;
141 }
142 if(a.formula.type != b.formula.type)
143 {
144 printf("device '%s.%s.%s' have different formula types\n", soc.name.c_str(),
145 dev.name.c_str(), a.name.c_str());
146 return false;
147 }
148 if(a.formula.string != b.formula.string)
149 {
150 printf("device '%s.%s.%s' have different formula string\n", soc.name.c_str(),
151 dev.name.c_str(), a.name.c_str());
152 return false;
153 }
154 /* addresses */
155 std::vector< std::pair< size_t, size_t > > map;
156 if(!build_map("register address", a.addr, b.addr, map))
157 return false;
158 for(size_t i = 0; i < map.size(); i++)
159 if(!compare_reg_addr(soc, dev, a, a.addr[map[i].first], b.addr[map[i].second]))
160 return false;
161 /* field */
162 map.clear();
163 if(!build_map("field", a.field, b.field, map))
164 return false;
165 for(size_t i = 0; i < map.size(); i++)
166 if(!compare_field(soc, dev, a, a.field[map[i].first], b.field[map[i].second]))
167 return false;
168 return true;
62} 169}
63 170
64void print_dev_desc(const soc_dev_t& dev) 171bool compare_dev_addr(const soc_t& soc, const soc_dev_t& dev, const soc_dev_addr_t& a,
172 const soc_dev_addr_t& b)
65{ 173{
66 printf(" DEV %s\n", dev.name.c_str()); 174 if(a.addr != b.addr)
67 for(size_t i = 0; i < dev.addr.size(); i++) 175 {
68 print_dev_addr_desc(dev.addr[i]); 176 printf("device address '%s.%s.%s' have different values\n", soc.name.c_str(),
69 for(size_t i = 0; i < dev.reg.size(); i++) 177 dev.name.c_str(), a.name.c_str());
70 print_reg_desc(dev.reg[i]); 178 return false;
179 }
180 else
181 return true;
71} 182}
72 183
73void print_soc_desc(const soc_t& soc) 184bool compare_dev(const soc_t& soc, const soc_dev_t& a, const soc_dev_t& b)
74{ 185{
75 printf("SOC %s (%s)\n", soc.name.c_str(), soc.desc.c_str()); 186 if(a.long_name != b.long_name)
76 for(size_t i = 0; i < soc.dev.size(); i++) 187 {
77 print_dev_desc(soc.dev[i]); 188 printf("device '%s.%s' have different long names\n", soc.name.c_str(),
189 a.name.c_str());
190 return false;
191 }
192 if(a.desc != b.desc)
193 {
194 printf("device '%s.%s' have different descriptions\n", soc.name.c_str(),
195 a.name.c_str());
196 return false;
197 }
198 if(a.version != b.version)
199 {
200 printf("device '%s.%s' have different versions\n", soc.name.c_str(),
201 a.name.c_str());
202 return false;
203 }
204 /* addresses */
205 std::vector< std::pair< size_t, size_t > > map;
206 if(!build_map("device address", a.addr, b.addr, map))
207 return false;
208 for(size_t i = 0; i < map.size(); i++)
209 if(!compare_dev_addr(soc, a, a.addr[map[i].first], b.addr[map[i].second]))
210 return false;
211 /* reg */
212 map.clear();
213 if(!build_map("register", a.reg, b.reg, map))
214 return false;
215 for(size_t i = 0; i < map.size(); i++)
216 if(!compare_reg(soc, a, a.reg[map[i].first], b.reg[map[i].second]))
217 return false;
218 return true;
219}
220
221bool compare_soc(const soc_t& a, const soc_t& b)
222{
223 if(a.name != b.name)
224 {
225 return printf("soc have different names\n");
226 return false;
227 }
228 if(a.desc != b.desc)
229 {
230 printf("soc '%s' have different descriptions\n", a.name.c_str());
231 return false;
232 }
233 std::vector< std::pair< size_t, size_t > > map;
234 if(!build_map("device", a.dev, b.dev, map))
235 return false;
236 for(size_t i = 0; i< map.size(); i++)
237 if(!compare_dev(a, a.dev[map[i].first], b.dev[map[i].second]))
238 return false;
239 return true;
240}
241
242int do_compare(int argc, char **argv)
243{
244 if(argc != 2)
245 return printf("compare mode expects two arguments\n");
246 soc_t soc[2];
247 if(!soc_desc_parse_xml(argv[0], soc[0]))
248 return printf("cannot read file '%s'\n", argv[0]);
249 if(!soc_desc_parse_xml(argv[1], soc[1]))
250 return printf("cannot read file '%s'\n", argv[1]);
251 if(compare_soc(soc[0], soc[1]))
252 printf("Files are identical.\n");
253 return 0;
254}
255
256int do_write(int argc, char **argv)
257{
258 if(argc != 2)
259 return printf("write mode expects two arguments\n");
260 soc_t soc;
261 if(!soc_desc_parse_xml(argv[0], soc))
262 return printf("cannot read file '%s'\n", argv[0]);
263 if(!soc_desc_produce_xml(argv[1], soc))
264 return printf("cannot write file '%s'\n", argv[1]);
265 return 0;
266}
267
268int do_check(int argc, char **argv)
269{
270 for(int i = 0; i < argc; i++)
271 {
272 soc_t soc;
273 if(!soc_desc_parse_xml(argv[i], soc))
274 {
275 printf("cannot read file '%s'\n", argv[i]);
276 continue;
277 }
278 printf("[%s]\n", argv[i]);
279 std::vector< soc_error_t > errs = soc.errors(true);
280 for(size_t i = 0; i < errs.size(); i++)
281 {
282 const soc_error_t& e = errs[i];
283 switch(e.level)
284 {
285 case SOC_ERROR_WARNING: printf("[WARN ] "); break;
286 case SOC_ERROR_FATAL: printf("[FATAL] "); break;
287 default: printf("[ UNK ] "); break;
288 }
289 printf("%s: %s\n", e.location.c_str(), e.message.c_str());
290 }
291 }
292 return 0;
293}
294
295int do_eval(int argc, char **argv)
296{
297 std::map< std::string, soc_word_t > map;
298 for(int i = 0; i < argc; i++)
299 {
300 std::string error;
301 std::string formula(argv[i]);
302 soc_word_t result;
303 if(strcmp(argv[i], "--var") == 0)
304 {
305 if(i + 1 >= argc)
306 break;
307 i++;
308 std::string str(argv[i]);
309 size_t pos = str.find('=');
310 if(pos == std::string::npos)
311 {
312 printf("invalid variable string '%s'\n", str.c_str());
313 continue;
314 }
315 std::string name = str.substr(0, pos);
316 std::string val = str.substr(pos + 1);
317 char *end;
318 soc_word_t v = strtoul(val.c_str(), &end, 0);
319 if(*end)
320 {
321 printf("invalid variable string '%s'\n", str.c_str());
322 continue;
323 }
324 printf("%s = %#lx\n", name.c_str(), (unsigned long)v);
325 map[name] = v;
326 continue;
327 }
328 if(!soc_desc_evaluate_formula(formula, map, result, error))
329 printf("error: %s\n", error.c_str());
330 else
331 printf("result: %lu (%#lx)\n", (unsigned long)result, (unsigned long)result);
332 }
333 return 0;
78} 334}
79 335
80void usage() 336void usage()
81{ 337{
82 printf("usage: tester <desc file>\n"); 338 printf("usage: tester <mode> [options]\n");
339 printf("modes:\n");
340 printf(" compare <desc file> <desc file>\n");
341 printf(" write <read file> <write file>\n");
342 printf(" check <files...>\n");
343 printf(" eval [<formula>|--var <name>=<val>]...\n");
83 exit(1); 344 exit(1);
84} 345}
85 346
86int main(int argc, char **argv) 347int main(int argc, char **argv)
87{ 348{
88 if(argc != 2) 349 if(argc < 2)
350 usage();
351 std::string mode = argv[1];
352 if(mode == "compare")
353 return do_compare(argc - 2, argv + 2);
354 else if(mode == "write")
355 return do_write(argc - 2, argv + 2);
356 else if(mode == "check")
357 return do_check(argc - 2, argv + 2);
358 else if(mode == "eval")
359 return do_eval(argc - 2, argv + 2);
360 else
89 usage(); 361 usage();
90 std::vector< soc_t > socs;
91 bool ret = soc_desc_parse_xml(argv[1], socs);
92 printf("parse result: %d\n", ret);
93 if(ret)
94 for(size_t i = 0; i < socs.size(); i++)
95 print_soc_desc(socs[i]);
96 return 0; 362 return 0;
97} \ No newline at end of file 363} \ No newline at end of file