Skip to content

Commit

Permalink
doc updates. Add more unittests
Browse files Browse the repository at this point in the history
  • Loading branch information
amykyta3 committed Jul 9, 2018
1 parent 6f226a0 commit 512a9a5
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 20 deletions.
66 changes: 66 additions & 0 deletions docs/implementation_notes/multi-file_compilation
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
--------------------------------------------------------------------------------
Multi-file Compilation
--------------------------------------------------------------------------------

The ability to split a SystemRDL register model into several RDL files seems like
an inherently useful way to manage a design that spans multiple components.

Unfortunately, the SystemRDL 2.0 spec provides no insight on how "compilation units"
are handled. Below are the assumptions I made to guide the implementation of this
compiler.


1. Each file is its own compilation unit
----------------------------------------

Semantics:
a. The contents of files included using one or more `include directives become
part of the compilation unit of the file within which they are included.
b. Declarations must be completed within the boundaries of a compilation unit.
If there is a declaration that is incomplete at the end of a compilation unit,
it shall be a compile error.
c. Any Verilog-style preprocessor macros defined within a file are discarded at the
end of the compilation unit.

Rationale:
Isolating each file provided to the compiler to a design unit reduces
confusing scenarios where things like preprocessor macros 'leak' unexpectedly
between files.


2. SystemRDL namespaces are global across compilation units
-----------------------------------------------------------
The root scope of the official SystemRDL namespaces are shared across files.

Specifically the three namespaces described in the SystemRDL 2.0 spec:
a. Type namespace
Component definitions, enum types, and struct types
b. Element namespace
In the $root scope, this is limited to signal instances.
c. Property namespace
User-defined properties declared in the root scope

Reiterating the concepts described in section 5.1.4: types, elements, and properties
shall be defined prior to being used. This is extended for compilation units and
means that the order in which files are compiled matters.

Rationale:
If supporting multiple file compile, then sharing these namespaces is
essential.
Enforcing that file order honor that identifiers are defined prior to being
used significantly simplifies the compiler design.


3. Default property assignments are limited to the compilation unit
-------------------------------------------------------------------

Any default property assignments made in the root scope are limited to the
current compilation unit. Default property assignments are discarded from the
root scope at the end of each compilation unit.

Rationale:
Allowing default property assignments to carry over between files/compilation
units would be incredibly confusing.
A default property assignment in a prior design unit's root scope would
inevitably influence all subsequent files, causing all kinds of unintended
consequences.
16 changes: 16 additions & 0 deletions docs/implementation_notes/systemrdl_spec_issues
Original file line number Diff line number Diff line change
Expand Up @@ -104,3 +104,19 @@ User-defined property's "type" attribute can not be "signal"?
Resolution:
None for now.
Implemented according to spec until I hear otherwise.

--------------------------------------------------------------------------------
Compilation units and their scope not described in SystemRDL spec
The SystemRDL 2.0 spec does not address the concept of "compilation units"
and how multiple RDL files share namespaces.

If multiple RDL files are compiled together, how are their namespaces shared?

Resolution:
I have provided my own interpretation of how compilation units in
SystemRDL should work.
Some concepts are borrowed from SystemVerilog, but are simplified significantly
in order to have the least "surprising" effects.

See "multi-file_compilation" notes for more details.

24 changes: 12 additions & 12 deletions docs/model_structure.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,20 @@ Once compiled, the resulting component tree is as follows:

The resulting tree has the following characteristics:

- Each component instance is represented by a :class:`~systemrdl.component.Component`
- Each component instance is represented by a :class:`~systemrdl.component.Component`
object.
- Any instances within a component are referenced as children of the component.
- The ``$root`` meta-component contains an instance of the elaborated top-level
- Any instances within a component are referenced as children of the component.
- The ``$root`` meta-component contains an instance of the elaborated top-level
addrmap, as well as any signals that were instantiated in the root namespace.
- All instances and their descendants are unique objects.
- Arrays of instances are encoded as a single object and storing the array's
- All instances and their descendants are unique objects.
- Arrays of instances are encoded as a single object and storing the array's
dimensions.
- Each instance in the component tree keeps a reference back to its original
- Each instance in the component tree keeps a reference back to its original
"as-defined" non-instance object.

- For example, instances ``A`` and ``B`` are both based off of the common
- For example, instances ``A`` and ``B`` are both based off of the common
component definition ``my_reg_t`` (shown in gray).
- Note that ``top`` and ``$root`` instances also have similar references, but
- Note that ``top`` and ``$root`` instances also have similar references, but
are not shown in the diagram above.

Node Overlay
Expand All @@ -51,10 +51,10 @@ unambiguous.

Each :class:`~systemrdl.node.Node` object provides the following:

- Reference to its corresponding :class:`~systemrdl.component.Component` instance.
- Reference to its immediate parent
- The current array index of an instance.
- Helper functions that simplify querying and traversing the register model.
- Reference to its corresponding :class:`~systemrdl.component.Component` instance.
- Reference to its immediate parent
- The current array index of an instance.
- Helper functions that simplify querying and traversing the register model.

Most of the your interaction with the register model should be through
:class:`~systemrdl.node.Node` objects.
Expand Down
29 changes: 22 additions & 7 deletions systemrdl/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ def __init__(self, message_printer=None):
def compile_file(self, path):
"""
Parse & compile a single file and append it to RDLCompiler's root
namespace
namespace.
If any exceptions (:class:`~systemrdl.messages.RDLCompileError` or other)
occur during compilation, then the RDLCompiler object should be discarded.
Parameters
----------
Expand All @@ -52,7 +55,7 @@ def compile_file(self, path):
Raises
------
:class:`~systemrdl.messages.RDLCompileError`
If any fatal compile error is encountered
If any fatal compile error is encountered.
"""

input_stream = FileStream(path)
Expand All @@ -76,18 +79,29 @@ def compile_file(self, path):
self.visitor.visit(parsed_tree)

# Reset default property assignments from namespace.
# They should not leak between files since that would be confusing.
# They should not be shared between files since that would be confusing.
self.namespace.default_property_ns_stack = [{}]

if self.msg.error_count:
self.msg.fatal("Compile aborted due to previous errors")

def elaborate(self, top_def_name=None, inst_name=None, parameters=None):
"""
Elaborates the design with the specified component definition from
the root namespace as the top-level component.
Elaborates the design for the given top-level addrmap component.
During elaboration, the following occurs:
- An instance of the ``$root`` meta-component is created.
- The addrmap component specified by ``top_def_name`` is instantiated as a
child of ``$root``.
- Expressions, parameters, and inferred address/field placements are elaborated.
- Validation checks are performed.
If a design contains multiple root-level addrmaps, ``elaborate()`` can be
called multiple times in order to elaborate each individually.
Currently, an RDLCompiler instance can only be elaborated once.
If any exceptions (:class:`~systemrdl.messages.RDLCompileError` or other)
occur during elaboration, then the RDLCompiler object should be discarded.
Parameters
----------
Expand All @@ -102,7 +116,7 @@ def elaborate(self, top_def_name=None, inst_name=None, parameters=None):
By default, instantiated name is the same as ``top_def_name``
parameters: TBD
Assign the top-component instance parameters
This feature is not implemented yet.
Raises
------
Expand Down Expand Up @@ -146,6 +160,7 @@ def elaborate(self, top_def_name=None, inst_name=None, parameters=None):
top_inst = deepcopy(top_def)
top_inst.is_instance = True
top_inst.original_def = top_def
top_inst.addr_offset = 0
if inst_name is not None:
top_inst.inst_name = inst_name
else:
Expand Down
14 changes: 14 additions & 0 deletions test/rdl_testcases/address_packing.rdl
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,17 @@ addrmap example_5_1_2_5_ex3 {
// and ((address % 0x80) == 0)
} example;
};

//------------------------------------------------------------------------------
// Hierarchical addressing
//------------------------------------------------------------------------------
addrmap hier {
reg some_reg { field {} a; };

regfile {
some_reg a[5][3]; // @ 0, size=4*5*3=60=0x3C
some_reg b[10]; // @ 0x3C, size=40=0x28
some_reg c[3][4]; // @0x64, size=48=0x30
} x, // @0, size=148=0x94
y[4]; // @0x100 size=148*4=592
}; // @0, size=740
Loading

0 comments on commit 512a9a5

Please sign in to comment.