Example #1
0
        /// <summary>
        /// Creates a fake process that is used to create the connection
        /// </summary>
        /// <param name="state">The validation state to use</param>
        /// <param name="scope">The active scope</param>
        /// <param name="connEntry">The connection entry to create the process for</param>
        /// <returns>A fake process instance</returns>
        public static Instance.Process CreateConnectProcess(Validation.ValidationState state, Validation.ScopeState scope, AST.ConnectEntry connEntry)
        {
            var lhs = state.FindSymbol(connEntry.Source, scope) ?? throw new ParserException($"Could not resolve symbol {connEntry.Source.SourceToken}", connEntry.Source);
            var rhs = state.FindSymbol(connEntry.Target, scope) ?? throw new ParserException($"Could not resolve symbol {connEntry.Target.SourceToken}", connEntry.Target);

            if (lhs is Instance.Signal lhs_signal && rhs is Instance.Signal rhs_signal)
            {
                return(IdentityHelper.CreateIdentityProcess(
                           state,
                           scope,
                           connEntry.SourceToken,
                           // Extract the bus name locally
                           new Name(connEntry.Source.SourceToken, connEntry.Source.Identifier.SkipLast(1).ToArray(), null).AsExpression(),
                           new Name(connEntry.Target.SourceToken, connEntry.Target.Identifier.SkipLast(1).ToArray(), null).AsExpression(),
                           // Assign just the named entry
                           new[] { lhs_signal.Source },
                           // Ensure we use the same type to avoid silent type-casting
                           new[] {
                    new BusSignalDeclaration(connEntry.Target.SourceToken,
                                             rhs_signal.Source.Name,
                                             lhs_signal.Source.Type,
                                             null,
                                             AST.SignalDirection.Normal
                                             )
                },
                           Instance.ProcessType.Connect
                           ));
            }
Example #2
0
        /// <summary>
        /// Creates instances for all signals of a bus
        /// </summary>
        /// <param name="state">The state to use</param>
        /// <param name="parent">The bus to create the signal instances for</param>
        private void CreateAndRegisterInstance(Validation.ValidationState state, Instance.Bus parent)
        {
            var scope = state.CurrentScope;

            foreach (var signal in parent.Source.Signals)
            {
                var s = new Instance.Signal(parent, signal);
                scope.TryAddSymbol(s.Name, s, signal.Name);
                parent.Instances.Add(s);
            }
        }
Example #3
0
        /// <summary>
        /// Performs a lookup to find the symbol and returns the datatype of the found symbol
        /// </summary>
        /// <param name="state">The current state</param>
        /// <param name="scope">The scope to use</param>
        /// <param name="name">The name to find</param>
        /// <returns>The datatype or <c>null</c></returns>
        private static DataType FindDataType(Validation.ValidationState state, AST.NameExpression name, ScopeState scope)
        {
            var symb = state.ResolveSymbol(name, scope);

            if (symb == null)
            {
                throw new ParserException($"Unable to find instance for name: {name.Name}", name);
            }

            if (symb is Instance.Variable variable)
            {
                return(variable.ResolvedType = state.ResolveTypeName(variable.Source.Type, scope));
            }
            else if (symb is Instance.Bus bus)
            {
                return(state.ResolveBusSignalTypes(bus, scope));
            }
            else if (symb is Instance.Signal signal)
            {
                return(signal.ResolvedType = state.ResolveTypeName(signal.Source.Type, scope));
            }
            else if (symb is Instance.ConstantReference constant)
            {
                return(constant.ResolvedType = state.ResolveTypeName(constant.Source.DataType, scope));
            }
            else if (symb is Instance.EnumFieldReference efr)
            {
                return(new AST.DataType(name.SourceToken, efr.ParentType.Source));
            }
            else if (symb is Instance.Literal literalInstance)
            {
                if (literalInstance.Source is AST.BooleanConstant)
                {
                    return(new AST.DataType(literalInstance.Source.SourceToken, ILType.Bool, 1));
                }
                else if (literalInstance.Source is AST.IntegerConstant)
                {
                    return(new AST.DataType(literalInstance.Source.SourceToken, ILType.SignedInteger, -1));
                }
                else if (literalInstance.Source is AST.FloatingConstant)
                {
                    return(new AST.DataType(literalInstance.Source.SourceToken, ILType.Float, -1));
                }
            }

            return(null);
        }
Example #4
0
        /// <summary>
        /// Creates all sub-instances from declarations
        /// </summary>
        /// <param name="state">The state to use</param>
        /// <param name="declarations">The declarations to process</param>
        /// <param name="parentInstances">The collection of instances to append to</param>
        private void CreateAndRegisterInstancesForDeclarations(Validation.ValidationState state, IEnumerable <AST.Declaration> declarations, List <Instance.IInstance> parentInstances)
        {
            var scope = state.CurrentScope;

            // Add all variables and locally defined busses
            foreach (var decl in declarations)
            {
                if (decl is EnumDeclaration en)
                {
                    var e = new Instance.EnumTypeReference(en);
                    scope.TryAddSymbol(e.Name, e, en.Name);
                    using (state.StartScope(e))
                        CreateAndRegisterInstance(state, e);
                    parentInstances.Add(e);
                }
                else if (decl is FunctionDefinition fdef)
                {
                    scope.TryAddSymbol(fdef.Name.Name, decl, fdef.Name);
                }
                else if (decl is ConstantDeclaration cdecl)
                {
                    var c = new Instance.ConstantReference(cdecl);
                    scope.TryAddSymbol(c.Name, c, cdecl.Name);
                    parentInstances.Add(c);
                }
                else if (decl is VariableDeclaration variable)
                {
                    var v = new Instance.Variable(variable);
                    scope.TryAddSymbol(v.Name, v, variable.Name);
                    parentInstances.Add(v);
                }
                else if (decl is BusDeclaration bus)
                {
                    var b = new Instance.Bus(bus);
                    scope.TryAddSymbol(b.Name, b, bus.Name);
                    using (state.StartScope(b))
                        CreateAndRegisterInstance(state, b);
                    parentInstances.Add(b);
                }
                else
                {
                    throw new ParserException($"Unable to process {decl.GetType()} inside a process", decl);
                }
            }
        }
Example #5
0
        /// <summary>
        /// Creates all sub-instances for a process
        /// </summary>
        /// <param name="state">The state to use</param>
        /// <param name="parent">The parent process</param>
        private void CreateAndRegisterInstance(Validation.ValidationState state, Instance.Process parent)
        {
            var scope = state.CurrentScope;

            CreateAndRegisterInstancesForDeclarations(state, parent.ProcessDefinition.Declarations, parent.Instances);

            // TODO: The scope should work within the statement tree. We can have nested statements....
            foreach (var loop in parent.Statements.All().OfType <AST.ForStatement>())
            {
                var l = new Instance.ForLoop(loop.Current);
                using (var sc = state.StartScope(l, loop.Current)) {
                    var varinst = new Instance.Variable(loop.Current.Variable);
                    sc.TryAddSymbol(loop.Current.Variable.Name.Name, varinst, loop.Current.Variable.SourceToken);
                }
                parent.Instances.Add(l);
            }

            // Find all function invocations so we can map parameters
            foreach (var func in parent.Statements.All().OfType <AST.FunctionStatement>())
            {
                var fdef = state.FindSymbol(func.Current.Name, scope);
                if (fdef == null)
                {
                    throw new ParserException($"No function named {func.Current.Name.AsString} found", func.Current);
                }
                if (!(fdef is AST.FunctionDefinition ffdef))
                {
                    throw new ParserException($"Expected a function for {func.Current.Name.AsString}, but found {fdef.GetType()}", func.Current);
                }

                var f = new Instance.FunctionInvocation(ffdef, func.Current);
                using (var sc = state.StartScope(f))
                    CreateAndRegisterInstancesForDeclarations(state, ffdef.Declarations, f.Instances);

                parent.Instances.Add(f);
            }
        }
Example #6
0
        /// <summary>
        /// Creates and registers all network declaration instances
        /// </summary>
        /// <param name="state">The state to use</param>
        /// <param name="networkDecls">The network declarations to instantiate</param>
        /// <param name="parentCollection"></param>
        private void CreateAndRegisterInstances(Validation.ValidationState state, IEnumerable <NetworkDeclaration> networkDecls, IList <Instance.IInstance> parentCollection)
        {
            var scope = state.CurrentScope;

            foreach (var decl in networkDecls)
            {
                if (decl is AST.BusDeclaration bus)
                {
                    var b = new Instance.Bus(bus);
                    scope.TryAddSymbol(b.Name, b, bus.Name);
                    using (state.StartScope(b))
                        CreateAndRegisterInstance(state, b);
                    parentCollection.Add(b);
                }
                else if (decl is AST.ConstantDeclaration cdecl)
                {
                    var cref = new Instance.ConstantReference(cdecl);
                    scope.TryAddSymbol(cref.Name, cref, cdecl.Name);
                    parentCollection.Add(cref);
                    continue;
                }
                else if (decl is AST.GeneratorDeclaration genDecl)
                {
                    var startSymbol  = state.ResolveToInteger(genDecl.SourceExpression, scope);
                    var finishSymbol = state.ResolveToInteger(genDecl.TargetExpression, scope);

                    // TODO: Need to fix array support for this to work correctly?
                    for (var i = startSymbol; i < finishSymbol; i++)
                    {
                        CreateAndRegisterInstances(state, genDecl.Networks, parentCollection);
                    }
                }
                else if (decl is AST.InstanceDeclaration instDecl)
                {
                    var sym = state.FindSymbol(instDecl.SourceItem, scope);
                    if (sym != null && sym is AST.Network netw)
                    {
                        // Recursively create network
                        // TODO: Guard against infinite recursion
                        parentCollection.Add(CreateAndRegisterInstance(state, instDecl, netw));
                    }
                    else if (sym != null && sym is AST.Process proc)
                    {
                        var p = new Instance.Process(instDecl, proc, Instance.ProcessType.Normal);
                        if (instDecl.Name.Name != null)
                        {
                            scope.TryAddSymbol(instDecl.Name.Name.Name, p, instDecl.Name.Name);
                        }

                        using (state.StartScope(p, instDecl))
                            CreateAndRegisterInstance(state, p);
                        parentCollection.Add(p);
                    }
                    else
                    {
                        if (sym == null)
                        {
                            throw new ParserException($"No item found with the name {instDecl.SourceItem}", decl);
                        }
                        else
                        {
                            throw new ParserException($"The item {instDecl.SourceItem} is not a process, but a {sym.GetType().Name}", decl);
                        }
                    }
                }
                else if (decl is AST.ConnectDeclaration connDecl)
                {
                    foreach (var connEntry in connDecl.Entries)
                    {
                        var p = IdentityHelper.CreateConnectProcess(state, scope, connEntry);
                        using (state.StartScope(p, connEntry))
                            CreateAndRegisterInstance(state, p);
                        parentCollection.Add(p);
                    }
                }
                else
                {
                    throw new ParserException($"Attempted to create an instance of type: {decl.GetType()}", decl);
                }
            }
        }
Example #7
0
        /// <summary>
        /// Creates the VHDL output files
        /// </summary>
        /// <param name="state">The validated network to create the files for</param>
        /// <param name="outputfolder">The folder to use as the base for the VHDL output</param>
        /// <param name="options">The options for creating the code</param>
        public static void CreateFiles(Validation.ValidationState state, string outputfolder, Program.Options options)
        {
            if (options.GHDLStandard != "93" && options.GHDLStandard != "93c")
            {
                throw new ParserException("Only 93 and 93c are currently supported", null);
            }

            var vhdlout = Path.GetFullPath(Path.Combine(outputfolder, options.VHDLOutputFolder));

            if (options.ClearTargetFolder && Directory.Exists(vhdlout))
            {
                if (string.IsNullOrWhiteSpace(options.VHDLOutputFolder) || options.VHDLOutputFolder.Trim().StartsWith("/"))
                {
                    throw new ArgumentException($"Refusing to delete folder, please supply a relative path: {options.VHDLOutputFolder}");
                }
                Directory.Delete(vhdlout, true);
            }

            if (!Directory.Exists(vhdlout))
            {
                Directory.CreateDirectory(vhdlout);
            }

            var config = new RenderConfig();

            if (options.CreateAocFiles)
            {
                Console.WriteLine("Note: aoc file generation activated, forcing options to be compatible with aoc output");
                config.REMOVE_ENABLE_FLAGS = true;
                config.RESET_SIGNAL_NAME   = "resetn";
                config.CLOCK_SIGNAL_NAME   = "clock";
                config.RESET_ACTIVE_LOW    = true;
                options.VHDLFileExtensions = "vhd";
            }

            var generator = new Codegen.VHDL.VHDLGenerator(state, config)
            {
                CSVTracename = options.TraceFile,
                Ticks        = File.Exists(options.TraceFile) ? File.ReadAllLines(options.TraceFile).Count() + 2 : 100,
                CustomFiles  = options.ExtraVHDLFiles
            };

            var rs = new Codegen.VHDL.VHDLGenerator.RenderState();

            var export = generator.GenerateExportModule(rs);

            File.WriteAllText(Path.Combine(vhdlout, Path.ChangeExtension("export.vhdl", options.VHDLFileExtensions)), export);

            var custtypes = generator.GenerateCustomTypes(rs);

            File.WriteAllText(Path.Combine(vhdlout, Path.ChangeExtension("customtypes.vhdl", options.VHDLFileExtensions)), custtypes);

            var tdoc = generator.GenerateMainModule(rs);

            File.WriteAllText(Path.Combine(vhdlout, Path.ChangeExtension("toplevel.vhdl", options.VHDLFileExtensions)), tdoc);

            var tbdoc = generator.GenerateTestbench(rs);

            File.WriteAllText(Path.Combine(vhdlout, Path.ChangeExtension("testbench.vhdl", options.VHDLFileExtensions)), tbdoc);

            var filenames = new Dictionary <Instance.Process, string>();

            foreach (var p in generator.AllRenderedProcesses)
            {
                var doc = generator.GenerateProcess(rs, p);
                var fn  = filenames[p] = generator.ProcessNames[p];
                File.WriteAllText(Path.Combine(vhdlout, Path.ChangeExtension(fn + ".vhdl", options.VHDLFileExtensions)), doc);
            }

            if (options.CreateXpf)
            {
                var txpf = generator.GenerateXpf(rs, filenames, options.VHDLFileExtensions);
                File.WriteAllText(Path.Combine(vhdlout, $"project.xpf"), txpf);
            }

            if (options.CreateAocFiles)
            {
                var aoclproj = generator.GenerateAocl(rs, filenames, options.VHDLFileExtensions);
                File.WriteAllText(Path.Combine(vhdlout, $"opencl_lib.xml"), aoclproj);
            }

            var makefile = generator.GenerateMakefile(rs, filenames, options.GHDLStandard, options.VHDLFileExtensions);

            File.WriteAllText(Path.Combine(vhdlout, $"Makefile"), makefile);

            generator.CopySupportFiles(vhdlout);
        }