aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/ic_reg_maps/common.py
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/ic_reg_maps/common.py')
-rw-r--r--host/lib/ic_reg_maps/common.py196
1 files changed, 196 insertions, 0 deletions
diff --git a/host/lib/ic_reg_maps/common.py b/host/lib/ic_reg_maps/common.py
new file mode 100644
index 000000000..24f5bf8be
--- /dev/null
+++ b/host/lib/ic_reg_maps/common.py
@@ -0,0 +1,196 @@
+#
+# Copyright 2010-2011 Ettus Research LLC
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+#
+
+import re
+import sys
+import math
+from Cheetah.Template import Template
+
+COMMON_TMPL = """\
+#import time
+/***********************************************************************
+ * This file was generated by $file on $time.strftime("%c")
+ **********************************************************************/
+
+\#ifndef INCLUDED_$(name.upper())_HPP
+\#define INCLUDED_$(name.upper())_HPP
+
+\#include <uhd/config.hpp>
+\#include <uhd/exception.hpp>
+\#include <boost/cstdint.hpp>
+\#include <set>
+
+class $(name)_t{
+public:
+ #for $reg in $regs
+ #if $reg.get_enums()
+ enum $reg.get_type(){
+ #for $i, $enum in enumerate($reg.get_enums())
+ #set $end_comma = ',' if $i < len($reg.get_enums())-1 else ''
+ $(reg.get_name().upper())_$(enum[0].upper()) = $enum[1]$end_comma
+ #end for
+ };
+ #end if
+ $reg.get_type() $reg.get_name();
+ #end for
+
+ $(name)_t(void){
+ _state = NULL;
+ #for $reg in $regs
+ $reg.get_name() = $reg.get_default();
+ #end for
+ }
+
+ ~$(name)_t(void){
+ delete _state;
+ }
+
+ $body
+
+ void save_state(void){
+ if (_state == NULL) _state = new $(name)_t();
+ #for $reg in $regs
+ _state->$reg.get_name() = this->$reg.get_name();
+ #end for
+ }
+
+ template<typename T> std::set<T> get_changed_addrs(void){
+ if (_state == NULL) throw uhd::runtime_error("no saved state");
+ //check each register for changes
+ std::set<T> addrs;
+ #for $reg in $regs
+ if(_state->$reg.get_name() != this->$reg.get_name()){
+ addrs.insert($reg.get_addr());
+ }
+ #end for
+ return addrs;
+ }
+
+ #for $mreg in $mregs
+ $mreg.get_type() get_$(mreg.get_name())(void){
+ return
+ #set $shift = 0
+ #for $reg in $mreg.get_regs()
+ ($(mreg.get_type())($reg.get_name() & $reg.get_mask()) << $shift) |
+ #set $shift = $shift + $reg.get_bit_width()
+ #end for
+ 0;
+ }
+
+ void set_$(mreg.get_name())($mreg.get_type() reg){
+ #set $shift = 0
+ #for $reg in $mreg.get_regs()
+ $reg.get_name() = (reg >> $shift) & $reg.get_mask();
+ #set $shift = $shift + $reg.get_bit_width()
+ #end for
+ }
+
+ #end for
+private:
+ $(name)_t *_state;
+};
+
+\#endif /* INCLUDED_$(name.upper())_HPP */
+"""
+
+def parse_tmpl(_tmpl_text, **kwargs):
+ return str(Template(_tmpl_text, kwargs))
+
+def to_num(arg): return int(eval(arg))
+
+class reg:
+ def __init__(self, reg_des):
+ try: self.parse(reg_des)
+ except Exception, e:
+ raise Exception, 'Error parsing register description: "%s"\nWhat: %s'%(reg_des, e)
+
+ def parse(self, reg_des):
+ x = re.match('^(\w*)\s*(\w*)\[(.*)\]\s*(\w*)\s*(.*)$', reg_des)
+ name, addr, bit_range, default, enums = x.groups()
+
+ #store variables
+ self._name = name
+ self._addr = to_num(addr)
+ if ':' in bit_range: self._addr_spec = sorted(map(int, bit_range.split(':')))
+ else: self._addr_spec = int(bit_range), int(bit_range)
+ self._default = to_num(default)
+
+ #extract enum
+ self._enums = list()
+ if enums:
+ enum_val = 0
+ for enum_str in map(str.strip, enums.split(',')):
+ if '=' in enum_str:
+ enum_name, enum_val = enum_str.split('=')
+ enum_val = to_num(enum_val)
+ else: enum_name = enum_str
+ self._enums.append((enum_name, enum_val))
+ enum_val += 1
+
+ def get_addr(self): return self._addr
+ def get_enums(self): return self._enums
+ def get_name(self): return self._name
+ def get_default(self):
+ for key, val in self.get_enums():
+ if val == self._default: return str.upper('%s_%s'%(self.get_name(), key))
+ return self._default
+ def get_type(self):
+ if self.get_enums(): return '%s_t'%self.get_name()
+ return 'boost::uint%d_t'%max(2**math.ceil(math.log(self.get_bit_width(), 2)), 8)
+ def get_shift(self): return self._addr_spec[0]
+ def get_mask(self): return hex(int('1'*self.get_bit_width(), 2))
+ def get_bit_width(self): return self._addr_spec[1] - self._addr_spec[0] + 1
+
+class mreg:
+ def __init__(self, mreg_des, regs):
+ try: self.parse(mreg_des, regs)
+ except Exception, e:
+ raise Exception, 'Error parsing meta register description: "%s"\nWhat: %s'%(mreg_des, e)
+
+ def parse(self, mreg_des, regs):
+ x = re.match('^~(\w*)\s+(.*)\s*$', mreg_des)
+ self._name, reg_names = x.groups()
+ regs_dict = dict([(reg.get_name(), reg) for reg in regs])
+ self._regs = [regs_dict[reg_name] for reg_name in map(str.strip, reg_names.split(','))]
+
+ def get_name(self): return self._name
+ def get_regs(self): return self._regs
+ def get_bit_width(self): return sum(map(reg.get_bit_width, self._regs))
+ def get_type(self):
+ return 'boost::uint%d_t'%max(2**math.ceil(math.log(self.get_bit_width(), 2)), 8)
+
+def generate(name, regs_tmpl, body_tmpl='', file=__file__, append=False):
+ #evaluate the regs template and parse each line into a register
+ regs = list(); mregs = list()
+ for entry in parse_tmpl(regs_tmpl).splitlines():
+ if entry.startswith('~'): mregs.append(mreg(entry, regs))
+ else: regs.append(reg(entry))
+
+ #evaluate the body template with the list of registers
+ body = '\n '.join(parse_tmpl(body_tmpl, regs=regs).splitlines())
+
+ #evaluate the code template with the parsed registers and arguments
+ code = parse_tmpl(COMMON_TMPL,
+ name=name,
+ regs=regs,
+ mregs=mregs,
+ body=body,
+ file=file,
+ )
+
+ #write the generated code to file specified by argv1
+ open(sys.argv[1], 'a' if append else 'w').write(code)