fabianschuiki / moore Goto Github PK
View Code? Open in Web Editor NEWA hardware compiler based on LLHD and CIRCT
Home Page: http://www.llhd.io
License: Apache License 2.0
A hardware compiler based on LLHD and CIRCT
Home Page: http://www.llhd.io
License: Apache License 2.0
Extend the lowering to HIR to cover every package body declarative item.
Implement type checking for component declarations.
Make use of the slog
create (already there as a dependency) to emit contextual information during compilation. Currently this is enabled with the --trace-scoreboard
option, but there are probably better ways to enable/disable these messages on-demand. By using the ability to nest the loggers, it should be possible to represent the dependencies that lead to calculations in the scoreboard as indentation.
Currently the representation of signal/variable assignment lvalues is fairly simple:
pub enum SigAssignTarget {
Name(SignalRef),
Aggregate,
}
Note that the Aggregate
variant is not even implement, nor are the cases of indexed, sliced, or selected signals. This needs to change. There needs to be code that explicitly unpacks the following AST nodes as potential lvalues:
Make sure that most of the code can be reused between signal and variable assignments.
Implement the lowering of process statements in an architecture to HIR.
Implement code generation for subprograms.
Array constraints are properly lowered to HIR. However, the compiler fails during typeck with the following message:
error: Array constraints on subtypes not yet supported
--> tests/vhdl/type_array.vhd:18:34-42:
|
| type T0 is array (1 to 10) of F (1 to 0);
| ^^^^^^^^
Fix this by properly applying the constraint to the subtype.
Verify that we impl the full set of VHDL types, and define some reasonable means to display them in a human-readable way. This should allow them to be printed in diagnostic messages.
The list of types as per IEEE 1076-2008 section 5 is:
(A, B, 'C', 'D')
range 0 to 42
or foo'range
range 0.0 to 4.2
range 0 to 42 units ns; us = 1000 ns; end units
array (integer range <>) of std_logic
array (31 downto 0) of std_logic
record A,B : integer; C : bit; end record
access integer
file of string
protected ... end protected
protected body ... end protected body
Properly type check subprograms. This requires some form of incarnations to be in place, mainly if generic parameters are part of the function. This requires #41 to be done.
The code that gathers the definitions in a scope and populates it with use clauses is pretty messy and incomplete. There is a DefsContext
which takes a first step in the right direction. But there is a lot more to do. Especially the code that just populates a scope is pretty much the same for every single entity. Surely this can be optimized.
It might also be possible to completely detach scopes from nodes, and just have scopes be a NodeId
that can never be asked for an HIR, type, or similar. This would allow scopes to remain quite general. The question then becomes: How do we know what node is needed to populate a scope with definitions.
VHDL types do not implement the Display
trait, nor any other means of pretty printing. This makes it hard to display types to the user, e.g. during typeck. Implement such a thing.
Since we're now generating the node IDs in the scoreboard when we lower things to HIR, remove the corresponding id
fields from the AST.
Lower subprogram declarations and bodies to HIR as described in IEEE 1076-2008 section 4.2. This will pave the way for type checking, code generation, and constant value calculation of subprogram and function calls. Furthermore, this is an important first step towards the implementation of incarnations.
The following is required:
Move the src/vhdl/score.rs
file into src/vhdl/score/mod.rs
and factor the HIR lowering, definition/scope population, type calculation, etc. out into separate files.
See IEEE 1076-2008 section 5.6.
At the moment only things that are actually used in the elaborated entity are type-checked, due to how the scoreboard is designed. It's not clear to me whether this is the best course of action in the long run. It would be better to have a type-check function also defined on entire entities, architectures, packages, etc., which calculate the types for the declarative items and statements contained within. This makes debugging easier, since the entire entity/architecture/package will be type-checked rather than just the ones that are used. At a later stage we can always introduce a flag that limits type-checking and codegen to the things that are actually used.
Consider switching to Servo's string-cache as an interner for strings. Check if it can be made to support selective case-insensitivity and replace our own common/name.rs
implementation.
Extend the lowering to HIR to cover every subprogram declarative item.
Extend the lowering to HIR to cover every block declarative item.
Implement type checking of attribute declarations and specifications.
The following snippet does not elaborate with cargo run -- score tests/vhdl/select_into_used_pkg.vhd -e A
:
-- tests/vhdl/select_into_used_pkg.vhd
package pkg is
type BIT is range 0 to 1;
end package;
library work;
use work.pkg;
entity A is
port (CK: out pkg.BIT);
-- ^^^ this fails at the moment
end;
architecture empty of A is begin end;
The compiler complains about not being able to find the pkg
in pkg.BIT
. But clearly this should be in scope due to the use work.pkg
above.
Add the following implicit statements to the beginning of every design unit's context items:
library STD, WORK;
use STD.STANDARD.all;
Record constraints need to be properly lowered from terms to HIR. Then typeck needs to apply them properly to the subtype.
Section 5.4.2 of IEEE 1076-2008 contains two examples for incomplete type definitions that result in types that are recursive or mutually dependent. Add these two examples as separate tests.
Add the predefined package TEXTIO
as per IEEE 1076-2008 section 16.4.
The scoreboard, or rather the scoreboard context should provide a function
fn span(&self, id: NodeId) -> Span
that maps any node reference to a span. This will make it easy to emit diagnostic messages, e.g. during typeck.
This function could make use of a hash map that is filled whenever set_ast
is called on the scoreboard. Or it could resort to requesting the HIR of a node and use the HasSpan
trait to get the span. The latter might be less work.
Implement code generation for process statements in architectures. In LLHD processes have an explicit port list and need to be explicitly instantiated. Therefore we need some means of gathering all signals read and written by a process. If that information is available, the mapping to LLHD becomes as simple as generating a new process and instantiating that in the surrounding entity.
For the following example containing a typedef enum
module typedef_enum (
input logic clk_i,
input logic rst_ni
);
typedef enum logic [1:0] { IDLE, BUSY, FAILED } state_t;
state_t state_d, state_q;
always_comb begin
state_d = state_q;
case (state_q)
IDLE: begin
state_d = BUSY;
end
BUSY: begin
state_d = FAILED;
end
endcase
end
always_ff @(posedge clk_i, negedge rst_ni) begin
if (rst_ni == 1'b0) begin
state_q <= IDLE;
end else begin
state_q <= state_d;
end
end
endmodule
name resolution fails for the defined enum
literals during elaboration:
error: `IDLE` has not been defined
--> typedef_enum.sv:11:13-17:
|
| IDLE: begin
| ^^^^
error: `BUSY` has not been defined
--> typedef_enum.sv:12:27-31:
|
| state_d = BUSY;
| ^^^^
error: `BUSY` has not been defined
--> typedef_enum.sv:14:13-17:
|
| BUSY: begin
| ^^^^
error: `FAILED` has not been defined
--> typedef_enum.sv:15:27-33:
|
| state_d = FAILED;
| ^^^^^^
error: `IDLE` has not been defined
--> typedef_enum.sv:22:24-28:
|
| state_q <= IDLE;
| ^^^^
fatal: name resolution failed
If lines 5 and 6 are replaced by
enum logic [1:0] { IDLE, BUSY, FAILED } state_d, state_q;
the module gets elaborated just fine.
Implement type checking of disconnection specifications.
Fix the following warnings about unused doc comments that occur when compiling with a reasonably recent version of rust:
warning: doc comment not used by rustdoc
--> src/vhdl/syntax/parser/rules.rs:1973:2
|
1973 | /// Parse the entity aspect.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_doc_comment)] on by default
warning: doc comment not used by rustdoc
--> src/vhdl/syntax/parser/rules.rs:2006:2
|
2006 | /// Parse the generic map aspect.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: doc comment not used by rustdoc
--> src/vhdl/syntax/parser/rules.rs:2009:2
|
2009 | /// Parse the port map aspect.
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
warning: doc comment not used by rustdoc
--> src/svlog/syntax/parser.rs:2058:2
|
2058 | /// Streaming concatenations have a "<<" or ">>" following the opening "{".
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(unused_doc_comment)] on by default
warning: doc comment not used by rustdoc
--> src/vhdl/score/lower_hir.rs:247:3
|
247 | /// Literals
| ^^^^^^^^^^^^
|
= note: #[warn(unused_doc_comment)] on by default
warning: doc comment not used by rustdoc
--> src/vhdl/score/typeck.rs:37:3
|
37 | /// For range constraints, we first have to check if the constraint is
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Should be an easy fix.
Make sure that every AST node keeps track of a span in the source file and implements the HasSpan
trait. Wrap things in Spanned
where appropriate and/or necessary.
Use the bitflags
crate to configure what additional debugging and logging messages to emit. The session could keep a set of verbosity flags which are inherited by the language-specific scoreboards. We may even want to have language-specific sessions, e.g. VhdlSession
wrapping around Session
.
The following debug output could be added:
Implement code generation for:
The compiler currently throws up when it sees an entity instantiation. To implement these, the instantiation should be lowered to HIR, typechecked, and have its generics bound to their constant values. This latter part is likely to require the incarnation concept from the svlog
crate to keep track of different values and types
Extend the lowering to HIR to cover every process declarative item.
Make sure that the CI build does not upload the result of a failed cargo doc
run. In the Travis configuration, combine the doc and upload command on the same line with &&
.
The root moore
crate is a binary at the moment. This is a bit inconvenient since the compiler itself should be as reusable as possible. Therefore the src/main.rs
file should go into src/bin/moore.rs
, and a new top-level src/lib.rs
file should be created:
// src/lib.rs
extern crate moore_common;
pub use moore_common::*;
extern crate moore_svlog as svlog;
extern crate moore_vhdl as vhdl;
Theoretically this should already be enough. Not sure if there will be a naming conflict because both the binary and the library will be called moore
. Can be fixed somehow.
Add a trait ArenaAllocator<T>
that provides an alloc
function for a specific type. Add a macro make_arenas!
that creates a struct containing a typed arena for each of the provided types, plus an additional list of sub-arenas / public members. The macro shall implement the ArenaAllocator
trait for each of the types. This simplifies code from
self.sb.arenas.ty.alloc(...);
to
self.sb.arenas.alloc(...);
and makes it easier to add new types to the arena.
Implement lowering of all expressions defined in IEEE 1076-2008 section 9.1 to HIR. Use termification to do so, which should make handling of aggregates and other rather wild syntactic issues easier. Then go from the Term
and map that to an expression. The building blocks are all there.
Make sure that hir::Expr
really only accepts what the aforementioned section of the standard defines as an expression. That is, get rid of all the weird range expressions. Maybe we can drop hir::Expr
and replace it directly with hir::ExprData
, since the only additional information that the former carries is a span. That span can be retained via Spanned<T>
.
Run rustfmt on the entire project during the CI build. This requires a nightly compiler, which might be available on Travis.
Implement type checking of configuration specifications.
Make sure that every HIR inherits the span information from the AST node upon lowering. Implement HasSpan
for every HIR node.
Not all type declarations are currently being lowered properly to HIR. Defining an array type for example yields the following error:
compiler bug: lowering to HIR of array type declaration not implemented
--> tests/vhdl/seq_signal_assignment_2.vhd:7:15-35:
|
| type bits is array (index) of bit;
| ^^^^^^^^^^^^^^^^^^^^
This should be a straight-forward fix, but requires extending the vhdl::ty
module with the missing types.
For the following (dummy) module
module type_cast;
typedef logic [47:0] some_type;
some_type some_signal;
int some_int;
assign some_int = int'(7.0);
assign some_signal = some_type'(some_int);
endmodule
the compiler fails at the first type cast with
error: Expected expression, found int instead
--> type_cast.sv:5:23-26:
|
| assign some_int = int'(7.0);
| ^^^
Without the assignment to some_int
and with an immediate value in the second type cast instead, the compiler fails there with
error: Expected , or ; after continuous assignment
--> type_cast.sv:6:35-36:
|
| assign some_signal = some_type'(7);
| ^
Add the failure
crate as a dependency 1. The crate provides a unified way to handle errors.
Extend the lowering to HIR to cover every package declarative item.
See IEEE 1076-2008 section 5.5.
Add the predefined package STANDARD
as per IEEE 1076-2008 section 16.3. Likely many of the functions need not be implemented directly, but are a result of the default function implementations that are generated for each type declaration.
Package STANDARD
defines the following:
type BOOLEAN
type BIT
type CHARACTER
type SEVERITY_LEVEL
type INTEGER
type REAL
type TIME
subtype DELAY_LENGTH
function NOW
subtype NATURAL
subtype POSITIVE
type STRING
type BOOLEAN_VECTOR
type BIT_VECTOR
type INTEGER_VECTOR
type REAL_VECTOR
type TIME_VECTOR
type FILE_OPEN_KIND
type FILE_OPEN_STATUS
attribute FOREIGN
Implement type checking for alias declarations.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.