.gitignore
[prop.git] / prop-src / bitfield.pcc
blobf4d33a95a5a7080f1eca03ad8fe97942f9d91acc
1 ///////////////////////////////////////////////////////////////////////////////
2 //
3 //  Bitfields and opcode encoding/decoding
4 //
5 ///////////////////////////////////////////////////////////////////////////////
6 #include <AD/contain/bitset.h>
7 #include "ir.ph"
8 #include "ast.ph"
9 #include "bitfield.ph"
10 #include "hashtab.h"
12 ///////////////////////////////////////////////////////////////////////////////
14 //  Instantiate the datatype FieldDef
16 ///////////////////////////////////////////////////////////////////////////////
17 instantiate datatype FieldDef, FieldLaw, List<FieldDef>, List<FieldLaw>;
19 ///////////////////////////////////////////////////////////////////////////////
21 //  Constructor and destructor
23 ///////////////////////////////////////////////////////////////////////////////
24 BitfieldCompiler:: BitfieldCompiler() {}
25 BitfieldCompiler::~BitfieldCompiler() {}
27 ///////////////////////////////////////////////////////////////////////////////
29 //  Environment for storing bitfields.
31 ///////////////////////////////////////////////////////////////////////////////
32 static HashTable bitfield_env(string_hash, string_equal);
34 ///////////////////////////////////////////////////////////////////////////////
36 //  Method to insert bitfield definition into environment.
38 ///////////////////////////////////////////////////////////////////////////////
39 void insert_bitfield (Id name, FieldDef field_def)
40 {  HashTable::Entry * e = bitfield_env.lookup(name);
41    if (e)
42    {  error ("%!redefinition of bitfield '%s'.\n"
43              "%!this is where it is last defined.\n",
44              ((FieldDef)e->v)->loc(), name, field_def->loc());
45    } else
46    {  bitfield_env.insert(name,field_def);
47    }
50 ///////////////////////////////////////////////////////////////////////////////
52 //  Check the bitfield patterns for consistency
54 ///////////////////////////////////////////////////////////////////////////////
55 void check_bitfield_consistency (Id name, int width, FieldDefs field_defs)
56 {  if (width < 0 || width >= 4096)
57    {  error ("%Lillegal width in bitfield '%s (%i)'\n", name, width);
58       return;
59    }
60    BitSet * referred = new (mem_pool, width) BitSet;
61    for_each (FieldDef, f, field_defs)
62    {  match (f)
63       {  // check that the field ranges are correct
64          FIELDdef { field_name, from_bit, to_bit ... } 
65          | from_bit < 0 || to_bit < 0 || from_bit > to_bit ||
66            from_bit >= width || to_bit >= width:
67          {  error ("%Lillegal bit range in bitfield '%s(%i)::%s (%i:%i)'\n", 
68                      name, width, field_name, from_bit, to_bit);
69          }
70       |  FIELDdef { from_bit, to_bit ... }:
71          {  for (int i = from_bit; i <= to_bit; i++)
72                referred->add(i);
73          }
74       |  _: // skip field constructor definitions
75       }
76    }
78    // Check that all the bits are covered by the bitfield declaration
79    for (int i = 0; i < width; )
80    {  if (! referred->contains(i))
81       {  int j;
82          for (j = i+1; j < width && ! referred->contains(j); j++);
83          msg ("%L%wrange (%i:%i) missing in bitfield '%s (%i)'\n",
84               i, j-1, name, width);
85          i = j;
86       } else { 
87          i++;
88       }
89    }
92 ///////////////////////////////////////////////////////////////////////////////
94 //  Method to compile a bitfield declaration
96 ///////////////////////////////////////////////////////////////////////////////
97 void BitfieldCompiler::define_bitfield 
98    (Id name, int width, FieldDefs field_defs, FieldLaws field_laws)
100    // make sure that the bitfields are range consistent.
101    check_bitfield_consistency(name, width, field_defs);
103    // insert into environment
104    for_each (FieldDef, f, field_defs)
105    {  match (f)
106       {  FIELDdef { field_name ... }:    { insert_bitfield(field_name, f); }
107       |  FIELDCONdef { field_name ... }: { insert_bitfield(field_name, f); }
108       }
109    }
112 ///////////////////////////////////////////////////////////////////////////////
114 //  Method to generate code for a bitfield declaration
116 ///////////////////////////////////////////////////////////////////////////////
117 void BitfieldCompiler::gen_bitfield
118    (Id name, int width, FieldDefs field_defs, FieldLaws laws)
120    pr ( "%^%/"
121         "%^// Definitions for bitfield '%s (%i)'"
122         "%^%/",
123         name, width
124       );
125    for_each (FieldLaw, l, laws)
126    {  match (l)
127       {  FIELDlaw { id, args, guard, exp }:
128          {  (*output) << "#define " << id << "(" << args << ") |" 
129                       << guard << " = " << exp << '\n';
130          }
131       }
132    }