Changeset 429 for proto


Ignore:
Timestamp:
Jul 3, 2010, 5:32:50 PM (9 years ago)
Author:
eamiri
Message:

-simd-carry option added

Location:
proto/Compiler
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • proto/Compiler/bitexpr.py

    r370 r429  
    101101        self.op_C = "adc128"
    102102        self.carry = carry
     103        self.op_advance_noint = "advance_with_carry"
     104        self.op_add_noint = "adc128_simd"
    103105        BitExpr.__init__(self, expr1, expr2, "Add")
    104106    def show(self): return 'Add(%s, %s)' % (self.operand1.show(), self.operand2.show())
     
    109111        self.op_C = "sbb128"
    110112        self.brw = brw
     113        self.op_sub_noint = "sbb128_simd"
    111114        BitExpr.__init__(self, expr1, expr2, "Sub")
    112115    def show(self): return 'Sub(%s, %s)' % (self.operand1.show(), self.operand2.show())
  • proto/Compiler/bitstream_compiler.py

    r422 r429  
    77#
    88
    9 import ast, py2bitexpr, string, sys
     9import ast, py2bitexpr, string, sys, copy
    1010
    1111class Program:
     
    1515        self.outfile_name = out_file
    1616
    17     def output(self, decl, stmts, templ):
     17    def output(self, decl, stream_stmts , block_stmts, templ):
    1818        templ = string.replace(templ, '@decl', decl)
    19         templ = string.replace(templ, '@stmts', stmts)
     19        templ = string.replace(templ, '@stream_stmts', stream_stmts)
     20        templ = string.replace(templ, '@block_stmts', block_stmts)
    2021        return templ
    2122
     
    3334        f.close()
    3435
    35     def generate_code(self, s, file_path):
     36    def generate_code(self, s, file_path, int_carry):
    3637        # FRONT END
    3738        s = ast.parse(s)
     
    5051        all_lives, s = py2bitexpr.eliminate_dead_code(s, set(livelist))
    5152        s = py2bitexpr.factor_out(s)
    52         s, livelist = py2bitexpr.process_while_loops(s)
     53        s, livelist = py2bitexpr.process_while_loops(s, int_carry)
     54       
    5355
    5456        # BACK END
    55         declarations = py2bitexpr.gen_declarations(s)
     57        declarations = py2bitexpr.gen_declarations(s, int_carry)
    5658        templ = self.read_template(file_path)
    5759
    58         templ = self.output(declarations, py2bitexpr.print_prog(s), templ)
     60        templ = self.output(declarations, py2bitexpr.print_stream_stmts(copy.deepcopy(s)), py2bitexpr.print_block_stmts(s, int_carry), templ)
    5961        self.write_final_code(templ)
    6062        return s
    6163
     64
     65def read_flags (params):
     66    flags = []
     67    non_flags = []
     68    l = len(params)
     69    for i in range(l):
     70        if params[i][0] == '-':
     71            flags.append(params[i])
     72        else:
     73            non_flags.append(params[i])
     74
     75    return flags, non_flags
     76
     77def int_carry(flags):
     78    l = len(flags)
     79    for i in range(l):
     80        if flags[i] == '-simd-carry':
     81            return False
     82        if flags[i] == '-int-carry':
     83            return True
     84    return True #default carry type is int
     85
     86def read_input(inp_file_name):
     87    mycode = ""
     88    inp_file = open(non_flags[1])
     89    for line in inp_file:
     90        mycode += line
     91    inp_file.close()
     92    return mycode
    6293###############################################################
    6394
    6495if __name__ == '__main__':
    65         mycode = ""
    6696        if len(sys.argv) < 2:
    67             print "Usage: python bitstream_compiler.py <input file> [output file]"
     97            print "Usage: python bitstream_compiler.py <input file> [output file] options"
    6898            #exit()
    6999
    70         #inp_file = open("parabix2.py")
    71         inp_file = open(sys.argv[1])
    72         last_slash = sys.argv[1].rfind("/")
    73         file_path = sys.argv[1][:last_slash+1]
     100        flags, non_flags = read_flags(sys.argv)
     101        last_slash = non_flags[1].rfind("/")
     102        file_path = non_flags[1][:last_slash+1]
    74103       
     104        out_file = "code.c"
     105        if len(non_flags) >= 3:
     106            out_file = non_flags[2]
    75107       
    76        
    77         for line in inp_file:
    78             mycode += line
    79         inp_file.close()
    80 
    81         out_file = "code.c"
    82         if len(sys.argv) >= 3:
    83             out_file = sys.argv[2]
    84         s = Program(out_file).generate_code(mycode, file_path)
     108        s = Program(out_file).generate_code(read_input(non_flags[1]), file_path, int_carry(flags))
  • proto/Compiler/py2bitexpr.py

    r421 r429  
    926926                if var_type == "int":
    927927                    ints.add(name)
     928                       
    928929        return {'int':ints, 'bitblock': bitblocks, 'array': arrays, 'struct': structs}
    929930
     
    951952    return res
    952953
    953 def gen_output(var_dic):
     954def gen_output(var_dic, int_carry):
    954955        s = ''
    955         for i in  var_dic['int']:
    956                 s+="int %s=0;\n"%i
    957 
    958956        for i in var_dic['bitblock']:
    959957                if i == AllOne:
    960958                        s += "BitBlock %s = simd_const_1(1);\n"%i
    961                 elif i== AllZero:
     959                elif i == AllZero:
    962960                        s+="BitBlock %s = simd_const_1(0);\n"%i
     961                elif i == "EOF_mask":
     962                        s+="BitBlock EOF_mask = simd_const_1(1);\n"
    963963                else:
    964964                        s+="BitBlock %s;\n"%i
     
    973973                s+="};\n"
    974974                s+="struct __%s__ %s;\n"%(i,i)
     975
     976        for i in  var_dic['int']:
     977                if int_carry:
     978                        s+="int %s=0;\n"%i
     979                else:
     980                        s+="BitBlock %s=AllZero;\n"%i
     981
     982
    975983
    976984        return s
     
    10031011        return vd
    10041012
    1005     """for loc in s[1:]:
    1006         more = get_vars(loc)
    1007 
    1008     vd = get_vars(bb[0].code)
    1009     for block in bb[1:]:
    1010         more = get_vars(block.code)
    1011         vd = merge_var_dic(vd, more)
    1012     declarations = gen_output(vd)
    1013     return declarations
    1014     """
    1015 
    1016 def gen_declarations(s):
     1013def gen_declarations(s, int_carry):
    10171014    vd = gen_var_dic(s)
    1018     return gen_output(vd)
    1019 #################################################################################################################
    1020 ## This class replaces all occurences of a reduced variable to its value --- Pass 7
     1015    return gen_output(vd, int_carry)
     1016#################################################################################################################
     1017## This class replaces all occurrences of a reduced variable to its value --- Pass 7
    10211018## *** This pass should change so that instead of recursing on the tree structure used before, it recurses on ***
    10221019## *** the new AST notation                                                                                   ***
     
    12861283carry_suffix = "_i"
    12871284
    1288 def fix_the_loop(loop):
     1285def fix_the_loop(loop, carry_type):
    12891286    carries = []
    12901287    for loc in loop.stmts:
     
    12931290    for item in carries:
    12941291        newvar = bitexpr.Var(item+carry_suffix)
    1295         loop.stmts.append(bitexpr.BitAssign(newvar, bitexpr.Or(newvar, bitexpr.Var(item), "int")))
     1292        loop.stmts.append(bitexpr.BitAssign(newvar, bitexpr.Or(newvar, bitexpr.Var(item), carry_type)))
    12961293    for item in carries:
    1297         loop.stmts.append(bitexpr.BitAssign( bitexpr.Var(item), bitexpr.FalseLiteral("int") ))
     1294        loop.stmts.append(bitexpr.BitAssign( bitexpr.Var(item), bitexpr.FalseLiteral(carry_type) ))
    12981295
    12991296    return loop, carries
    13001297
    1301 def process_while_loops(code):
     1298def process_while_loops(code, int_carry):
    13021299    all = []
    13031300    update = {}
     1301   
     1302    if int_carry:
     1303        carry_type = "int"
     1304    else:
     1305        carry_type = "vector"
     1306   
    13041307    for index, loc in enumerate(code):
    13051308        if isinstance(loc, bitexpr.WhileLoop):
    1306             update[index] = fix_the_loop(loc)
     1309            update[index] = fix_the_loop(loc, carry_type)
    13071310            for i in update[index][1]:
    13081311                all.append(i)
     
    13181321        code[key] = update[key][0]
    13191322        carry_variable = bitexpr.Var("CarryTemp"+str(key))
    1320         code[key].stmts.insert(0, bitexpr.BitAssign(carry_variable, bitexpr.FalseLiteral("int")))
     1323        code[key].stmts.insert(0, bitexpr.BitAssign(carry_variable, bitexpr.FalseLiteral(carry_type)))
    13211324        for item in update[key][1][2:]:
    1322             code.insert(key+1, bitexpr.BitAssign(carry_variable, bitexpr.Or(carry_variable, bitexpr.Var(item), "int")))
     1325            code.insert(key+1, bitexpr.BitAssign(carry_variable, bitexpr.Or(carry_variable, bitexpr.Var(item), carry_type)))
    13231326        if len(update[key][1]) == 1:
    13241327            code.insert(key+1, bitexpr.BitAssign(carry_variable, bitexpr.Var(update[key][1][0])))
    13251328        elif len(update[key][1]) > 1:
    1326             code.insert(key+1, bitexpr.BitAssign(carry_variable, bitexpr.Or(bitexpr.Var(update[key][1][0]), bitexpr.Var(update[key][1][1]), "int")))
     1329            code.insert(key+1, bitexpr.BitAssign(carry_variable, bitexpr.Or(bitexpr.Var(update[key][1][0]), bitexpr.Var(update[key][1][1]), carry_type)))
    13271330        for item in update[key][1]:
    1328             code.insert(key+1, bitexpr.BitAssign(bitexpr.Var(item+carry_suffix), bitexpr.FalseLiteral("int")))
     1331            code.insert(key+1, bitexpr.BitAssign(bitexpr.Var(item+carry_suffix), bitexpr.FalseLiteral(carry_type)))
    13291332        for item in update[key][1]:
    13301333            code.insert(key+1, bitexpr.BitAssign(bitexpr.Var(item), bitexpr.Var(item+carry_suffix)))
     
    14581461        assert (1==0)
    14591462
    1460 def print_prog(s, indent = 0):
     1463def print_block_stmts(s, int_carry, indent = 0):
    14611464    indent_unit = 4
    14621465    code = ""
     
    14651468    if isinstance(s[0], bitexpr.If):
    14661469        code = generate_statement(s[0].control_expr, indent, "if")
    1467         code += print_prog(s[0].true_branch, indent+indent_unit)
     1470        code += print_block_stmts(s[0].true_branch, int_carry, indent+indent_unit)
    14681471        code += " "*indent+"}\n"
    14691472        code += " "*indent+"else {\n"
    1470         code += print_prog(s[0].false_branch, indent+indent_unit)
     1473        code += print_block_stmts(s[0].false_branch, int_carry, indent+indent_unit)
    14711474        code += " "*indent+"}\n"
    14721475
    1473     if isinstance(s[0], bitexpr.WhileLoop):
    1474         #code = generate_statement(s[0].control_expr, indent, "while")
    1475         code = "\n%s((%s)||((256&%s)%s)) {\n"%(" "*indent+"while"+" ", generate_condition(s[0].control_expr), s[0].carry_expr.var.varname, ">0")
    1476         code += print_prog(s[0].stmts, indent+indent_unit)
     1476    elif isinstance(s[0], bitexpr.WhileLoop):
     1477        if int_carry:
     1478                code = "\n%s((%s)||((256&%s)%s)) {\n"%(" "*indent+"while"+" ", generate_condition(s[0].control_expr), s[0].carry_expr.var.varname, ">0")
     1479        else:
     1480                        code = "\n%s((%s)||(bitblock_has_bit(%s))) {\n"%(" "*indent+"while"+" ", generate_condition(s[0].control_expr), s[0].carry_expr.var.varname)
     1481        code += print_block_stmts(s[0].stmts, int_carry, indent+indent_unit)
    14771482        code += " "*indent+"}\n"
    1478 
    1479     if isinstance(s[0], bitexpr.BitAssign) and not (isinstance(s[0].RHS, bitexpr.Add) or isinstance(s[0].RHS, bitexpr.Sub)):
     1483    elif (isinstance(s[0].RHS, bitexpr.Const)):
     1484        pass
     1485 
     1486    elif isinstance(s[0], bitexpr.BitAssign) and not (isinstance(s[0].RHS, bitexpr.Add) or isinstance(s[0].RHS, bitexpr.Sub)):
     1487
    14801488        code += " "*indent + s[0].LHS.varname
    14811489        code += " = "
     
    15041512                code += s[0].RHS.operand2.varname
    15051513                code += ";\n"
    1506             elif isinstance(s[0].RHS, bitexpr.Const):
    1507                 code += "sisd_from_int(%i);"%s[0].RHS.n
    1508                 code += "\n"
    15091514            elif isinstance(s[0].RHS, bitexpr.FalseLiteral):
    15101515                code += "0;\n"
    1511     if isinstance(s[0], bitexpr.BitAssign) and (isinstance(s[0].RHS, bitexpr.Add) or isinstance(s[0].RHS, bitexpr.Sub)):
     1516    elif isinstance(s[0], bitexpr.BitAssign) and (isinstance(s[0].RHS, bitexpr.Add) or isinstance(s[0].RHS, bitexpr.Sub)) and int_carry:
    15121517            if isinstance(s[0].RHS, bitexpr.Add):
    15131518                code += " "*indent + s[0].RHS.op_C + "("
     
    15301535                code += s[0].LHS.varname
    15311536                code += ");\n"
     1537    elif isinstance(s[0], bitexpr.BitAssign) and (isinstance(s[0].RHS, bitexpr.Add) or isinstance(s[0].RHS, bitexpr.Sub)) and (not int_carry):
     1538                        if isinstance(s[0].RHS, bitexpr.Add) and (s[0].RHS.operand1.varname == s[0].RHS.operand2.varname):
     1539                                code += " "*indent + s[0].RHS.op_advance_noint + "("
     1540                                code += s[0].RHS.operand1.varname
     1541                                code += ', '
     1542                                code += s[0].RHS.carry
     1543                                code += ", "
     1544                                code += s[0].LHS.varname
     1545                                code += ");\n"
     1546                        elif isinstance(s[0].RHS, bitexpr.Add):
     1547                                code += " "*indent + s[0].RHS.op_add_noint + "("
     1548                                code += s[0].RHS.operand1.varname
     1549                                code += ', '
     1550                                code += s[0].RHS.operand2.varname
     1551                                code += ', '
     1552                                code += s[0].RHS.carry
     1553                                code += ", "
     1554                                code += s[0].LHS.varname
     1555                                code += ");\n"
     1556                        elif isinstance(s[0].RHS, bitexpr.Sub):
     1557                                code += " "*indent + s[0].RHS.op_sub_noint + "("
     1558                                code += s[0].RHS.operand1.varname
     1559                                code += ', '
     1560                                code += s[0].RHS.operand2.varname
     1561                                code += ', '
     1562                                code += s[0].RHS.brw
     1563                                code += ", "
     1564                                code += s[0].LHS.varname
     1565                                code += ");\n"
    15321566    s.pop(0)
    1533     return code+print_prog(s, indent)
     1567    return code+print_block_stmts(s, int_carry, indent)
     1568
     1569
     1570def print_stream_stmts(s, indent = 0):
     1571    indent_unit = 4
     1572    code = ""
     1573    if len(s) == 0:
     1574        return ""
     1575    elif isinstance(s[0], bitexpr.BitAssign):
     1576        if (isinstance(s[0].RHS, bitexpr.Const)):
     1577            code += " "*indent + s[0].LHS.varname
     1578            code += " = "
     1579            code += "sisd_from_int(%i);"%s[0].RHS.n
     1580            code += "\n"
     1581
     1582    s.pop(0)
     1583    return code+print_stream_stmts(s, indent)
    15341584
    15351585#################################################################################################################
  • proto/Compiler/sse_simd.h

    r346 r429  
    644644
    645645
    646 void print_bit_block(char * var_name, SIMD_type v) {
     646void print_bit_block(const char * var_name, SIMD_type v) {
    647647  union {SIMD_type vec; unsigned char elems[8];} x;
    648   x.vec = v;
     648  x.vec = v;d
    649649  unsigned char c, bit_reversed;
    650650  int i;
     
    652652  for (i = 0; i < sizeof(SIMD_type); i++) {
    653653    c = x.elems[i];
    654      printf("%02X ", c); 
     654     printf("%02X ", c);
    655655  }
    656656  printf("\n");
     
    703703
    704704
    705 #endif
    706 
     705#define double_int64_adc(x1, x2, y1, y2, rslt1, rslt2, carry) \
     706  __asm__  ("sahf\n\t" \
     707        "adc %[e1], %[z1]\n\t" \
     708        "adc %[e2], %[z2]\n\t" \
     709        "lahf\n\t" \
     710     : [z1] "=r" (rslt1), [z2] "=r" (rslt2), [carryflag] "=a" (carry) \
     711         : "[z1]" (x1), "[z2]" (x2), \
     712           [e1] "r" (y1), [e2] "r" (y2), \
     713           "[carryflag]" (carry) \
     714         : "cc")
     715
     716#define adc128(first, second, carry, sum) \
     717do\
     718{\
     719  union {__m128i bitblock;\
     720         uint64_t int64[2];} rslt;\
     721\
     722  union {__m128i bitblock;\
     723         uint64_t int64[2];} x;\
     724\
     725  union {__m128i bitblock;\
     726         uint64_t int64[2];} y;\
     727\
     728  x.bitblock = first;\
     729  y.bitblock = second;\
     730\
     731  double_int64_adc(x.int64[0], x.int64[1], y.int64[0], y.int64[1], rslt.int64[0], rslt.int64[1], carry);\
     732  sum = rslt.bitblock;\
     733}while(0)
     734
     735
     736
     737#define double_int64_sbb(x1, x2, y1, y2, rslt1, rslt2, carry) \
     738  __asm__  ("sahf\n\t" \
     739        "sbb %[e1], %[z1]\n\t" \
     740        "sbb %[e2], %[z2]\n\t" \
     741        "lahf\n\t" \
     742     : [z1] "=r" (rslt1), [z2] "=r" (rslt2), [carryflag] "=a" (carry) \
     743         : "[z1]" (x1), "[z2]" (x2), \
     744           [e1] "r" (y1), [e2] "r" (y2), \
     745           "[carryflag]" (carry) \
     746         : "cc")
     747
     748#define sbb128(first, second, carry, sum) \
     749do\
     750{ union {__m128i bitblock;\
     751         uint64_t int64[2];} rslt;\
     752\
     753  union {__m128i bitblock;\
     754         uint64_t int64[2];} x;\
     755\
     756  union {__m128i bitblock;\
     757         uint64_t int64[2];} y;\
     758\
     759  x.bitblock = first;\
     760  y.bitblock = second;\
     761\
     762  double_int64_sbb(x.int64[0], x.int64[1], y.int64[0], y.int64[1], \
     763                   rslt.int64[0], rslt.int64[1], carry);\
     764  sum = rslt.bitblock;\
     765}while(0)
     766
     767
     768
     769#define adc128_simd(x, y, carry,  sum) \
     770do{ \
     771  SIMD_type gen = simd_and(x, y); \
     772  SIMD_type prop = simd_or(x, y); \
     773  SIMD_type partial = simd_add_64(simd_add_64(x, y), *carry); \
     774  SIMD_type c1 = sisd_slli(simd_srli_64(simd_or(gen, simd_andc(prop, partial)), 63), 64); \
     775  *sum = simd_add_64(c1, partial); \
     776  *carry = sisd_srli(simd_or(gen, simd_andc(prop, *sum)), 127); \
     777} while(0)
     778
     779
     780#define sbb128_simd(x, y, borrow, difference) \
     781do {\
     782  SIMD_type gen = simd_andc(y, x); \
     783  SIMD_type prop = simd_not(simd_xor(x, y)); \
     784  SIMD_type partial = simd_sub_64(simd_sub_64(x, y), *borrow); \
     785  SIMD_type b1 = sisd_slli(simd_srli_64(simd_or(gen, simd_and(prop, partial)), 63), 64); \
     786  *difference = simd_sub_64(partial, b1); \
     787  *borrow = sisd_srli(simd_or(gen, simd_and(prop, *difference)), 127); \
     788}while(0)
     789
     790
     791#define advance_with_carry(cursor, carry, rslt)\
     792do{\
     793  SIMD_type shift_out = simd_srli_64(cursor, 63);\
     794  SIMD_type low_bits = simd_mergel_64(shift_out, carry);\
     795  carry = sisd_srli(shift_out, 64);\
     796  rslt = simd_or(simd_add_64(cursor, cursor), low_bits);\
     797}while(0)
     798
     799#endif
     800
  • proto/Compiler/template.c

    r418 r429  
    1212
    1313
    14 #define BUFFER_PROFILING
    15 
     14#include "perfsec.h"
     15//#define BUFFER_PROFILING
    1616#ifdef BUFFER_PROFILING
    17 #include "perfsec.h"
    1817BOM_Table * parser_timer;
    1918#endif
     
    7776} \
    7877
    79 #define double_int64_adc(x1, x2, y1, y2, rslt1, rslt2, carry) \
    80   __asm__  ("sahf\n\t" \
    81         "adc %[e1], %[z1]\n\t" \
    82         "adc %[e2], %[z2]\n\t" \
    83         "lahf\n\t" \
    84      : [z1] "=r" (rslt1), [z2] "=r" (rslt2), [carryflag] "=a" (carry) \
    85          : "[z1]" (x1), "[z2]" (x2), \
    86            [e1] "r" (y1), [e2] "r" (y2), \
    87            "[carryflag]" (carry) \
    88          : "cc")
    89 
    90 #define adc128(first, second, carry, sum) \
    91 do\
    92 {\
    93   union {__m128i bitblock;\
    94          uint64_t int64[2];} rslt;\
    95 \
    96   union {__m128i bitblock;\
    97          uint64_t int64[2];} x;\
    98 \
    99   union {__m128i bitblock;\
    100          uint64_t int64[2];} y;\
    101 \
    102   x.bitblock = first;\
    103   y.bitblock = second;\
    104 \
    105   double_int64_adc(x.int64[0], x.int64[1], y.int64[0], y.int64[1], rslt.int64[0], rslt.int64[1], carry);\
    106   sum = rslt.bitblock;\
    107 }while(0)
    108 
    109 
    110 
    111 #define double_int64_sbb(x1, x2, y1, y2, rslt1, rslt2, carry) \
    112   __asm__  ("sahf\n\t" \
    113         "sbb %[e1], %[z1]\n\t" \
    114         "sbb %[e2], %[z2]\n\t" \
    115         "lahf\n\t" \
    116      : [z1] "=r" (rslt1), [z2] "=r" (rslt2), [carryflag] "=a" (carry) \
    117          : "[z1]" (x1), "[z2]" (x2), \
    118            [e1] "r" (y1), [e2] "r" (y2), \
    119            "[carryflag]" (carry) \
    120          : "cc")
    121 
    122 #define sbb128(first, second, carry, sum) \
    123 do\
    124 { union {__m128i bitblock;\
    125          uint64_t int64[2];} rslt;\
    126 \
    127   union {__m128i bitblock;\
    128          uint64_t int64[2];} x;\
    129 \
    130   union {__m128i bitblock;\
    131          uint64_t int64[2];} y;\
    132 \
    133   x.bitblock = first;\
    134   y.bitblock = second;\
    135 \
    136   double_int64_sbb(x.int64[0], x.int64[1], y.int64[0], y.int64[1], \
    137                    rslt.int64[0], rslt.int64[1], carry);\
    138   sum = rslt.bitblock;\
    139 }while(0)
     78     
    14079
    14180       
     
    14584void do_process(FILE *infile, FILE *outfile) {
    14685
    147   @decl
     86@decl
    14887
    14988  BytePack U8[8];
     
    15695  char * srclimit;
    15796
     97
    15898 
    15999  srcbuf = (char *) malloc(BUFFER_SIZE+BLOCK_SIZE);
     
    163103  }
    164104 
    165   EOF_mask = simd_const_1(1);
    166105  chars_read = fread((void *)srcbuf, 1, BUFFER_SIZE, infile);
    167106  srclimit = srcbuf + chars_read;
     107
     108@stream_stmts
    168109
    169110  while(chars_read>0){
     
    199140      array_bit__7_ &= EOF_mask;
    200141
    201       @stmts
    202 
     142      @block_stmts
     143
     144     
    203145      if (bitblock_has_bit(error_mask)) {
    204146        errpos = block_pos + buf_pos + count_forward_zeroes(error_mask);
Note: See TracChangeset for help on using the changeset viewer.