/// <summary> /// Renders a single ExpressionStatement with the given indentation /// </summary> /// <returns>The VHDL lines in the statement.</returns> /// <param name="method">The method the statement belongs to.</param> /// <param name="s">The statement to render.</param> /// <param name="indentation">The indentation to use.</param> private IEnumerable <string> RenderStatement(AST.Method method, AST.ExpressionStatement s, int indentation) { var indent = new string(' ', indentation); var value = RenderExpression(s.Expression); if (!string.IsNullOrWhiteSpace(value)) { yield return($"{indent}{value};"); } }
public string BodyRegion(RenderStateProcess renderer, int indentation) { var initialdata = (Array)renderer.Process.SharedVariables.First(x => x.Name == "m_memory").DefaultValue; var size = initialdata.Length; var datawidth = VHDLHelper.GetBitWidthFromType(initialdata.GetType().GetElementType()); var addrwidth = (int)Math.Ceiling(Math.Log(initialdata.Length, 2)); var datavhdltype = renderer.Parent.TypeLookup[renderer.Process.InputBusses.First().Signals.First(x => x.Name == nameof(SME.Components.SinglePortMemory <int> .IControl.Data))]; var addrvhdltype = renderer.Parent.TypeLookup[renderer.Process.InputBusses.First().Signals.First(x => x.Name == nameof(SME.Components.SinglePortMemory <int> .IControl.Address))]; var control_bus_data_name = $"{ nameof(SME.Components.SinglePortMemory<int>.Control) }_{ nameof(SME.Components.SinglePortMemory<int>.IControl.Data) }"; var control_bus_addr_name = $"{ nameof(SME.Components.SinglePortMemory<int>.Control) }_{ nameof(SME.Components.SinglePortMemory<int>.IControl.Address) }"; var control_bus_enabled_name = $"{ nameof(SME.Components.SinglePortMemory<int>.Control) }_{ nameof(SME.Components.SinglePortMemory<int>.IControl.Enabled) }"; var control_bus_iswriting_name = $"{ nameof(SME.Components.SinglePortMemory<int>.Control) }_{ nameof(SME.Components.SinglePortMemory<int>.IControl.IsWriting) }"; var readresult_bus_data_name = $"{nameof(SME.Components.SinglePortMemory<int>.ReadResult)}_{ nameof(SME.Components.SinglePortMemory<int>.IReadResult.Data) }"; var asm_write = new AST.AssignmentExpression( new AST.IdentifierExpression( new AST.Signal( control_bus_data_name + "_Vector" ) ), new AST.IdentifierExpression( new AST.Signal( control_bus_data_name ) ) ); var asm_read = new AST.AssignmentExpression( new AST.IdentifierExpression( new AST.Signal( readresult_bus_data_name ) ), new AST.IdentifierExpression( new AST.Signal( readresult_bus_data_name + "_Vector" ) ) ); // Assign the vhdl types so the type conversion is done correctly renderer.Parent.TypeLookup[asm_write.Left] = renderer.Parent.TypeLookup[((AST.IdentifierExpression)asm_write.Left).Target] = renderer.Parent.TypeLookup[asm_read.Right] = renderer.Parent.TypeLookup[((AST.IdentifierExpression)asm_read.Right).Target] = renderer.Parent.TypeScope.GetStdLogicVector(datawidth); renderer.Parent.TypeLookup[asm_write.Right] = renderer.Parent.TypeLookup[((AST.IdentifierExpression)asm_write.Right).Target] = renderer.Parent.TypeLookup[asm_read.Left] = renderer.Parent.TypeLookup[((AST.IdentifierExpression)asm_read.Left).Target] = datavhdltype; var transformer = new Transformations.InjectTypeConversions(renderer.Parent, null); var asm_write_stm = new AST.ExpressionStatement(asm_write); asm_write_stm.UpdateParents(); var asm_read_stm = new AST.ExpressionStatement(asm_read); asm_read_stm.UpdateParents(); transformer.Transform(asm_write); transformer.Transform(asm_read); var template = $@" type ram_type is array ({size - 1} downto 0) of std_logic_vector ({datawidth - 1} downto 0); signal RAM : ram_type := { VHDLHelper.GetArrayAsAssignmentList(initialdata, inverse: true) }; signal { control_bus_data_name }_Vector: std_logic_vector ({datawidth - 1} downto 0); signal { readresult_bus_data_name }_Vector: std_logic_vector ({datawidth - 1} downto 0); signal { control_bus_addr_name }_Vector: std_logic_vector ({addrwidth - 1} downto 0); begin process (CLK) begin if (CLK'event and CLK = '1') then if ({ control_bus_enabled_name } = '1') then { readresult_bus_data_name }_Vector <= RAM(to_integer(unsigned({ control_bus_addr_name }_Vector))); if ({ control_bus_iswriting_name } = '1') then RAM(to_integer(unsigned({ control_bus_addr_name }_Vector))) <= { control_bus_data_name }_Vector; end if; end if; end if; end process; {renderer.Process.InstanceName}_Helper: process(RST, CLK, RDY) begin if RST = '1' then FIN <= '0'; elsif rising_edge(CLK) then FIN <= not RDY; end if; end process; { control_bus_addr_name }_Vector <= STD_LOGIC_VECTOR(resize(unsigned({ control_bus_addr_name }), {addrwidth})); {renderer.Helper.RenderExpression(asm_write_stm.Expression)}; {renderer.Helper.RenderExpression(asm_read_stm.Expression)}; "; return(VHDLHelper.ReIndentTemplate(template, indentation)); }
/// <summary> /// Applies the transformation /// </summary> /// <returns>The transformed item.</returns> /// <param name="el">The item to visit.</param> public ASTItem Transform(ASTItem el) { var ss = el as SwitchStatement; if (ss == null) return el; var exptype = State.VHDLType(ss.SwitchExpression); // Extract expression types var targets = ss .Cases .SelectMany(x => x.Item1) .Where(x => x != null && !(x is EmptyExpression)) .Select(x => State.VHDLType(x)) .Distinct() .ToArray(); // Case where the expressions are all integer literals, // but the source is some numeric if (targets.Length == 1 && targets.First() != exptype) { var mp = ss.GetNearestParent<Method>(); if (mp != null) { var targettype = ss .Cases .SelectMany(x => x.Item1) .First(x => x != null && !(x is EmptyExpression)) .SourceResultType; // Create a variable the same type as the cases // and set it to the switch expression var nvar = State.RegisterTemporaryVariable(mp, targettype); State.TypeLookup[nvar] = targets.First(); var nvexp = new IdentifierExpression() { Name = nvar.Name, SourceExpression = ss.SwitchExpression.SourceExpression, SourceResultType = nvar.CecilType, Target = nvar }; var asss = new AST.ExpressionStatement() { Expression = new AST.AssignmentExpression() { Left = nvexp, Operator = ICSharpCode.Decompiler.CSharp.Syntax.AssignmentOperatorType.Assign, Right = ss.SwitchExpression, SourceExpression = ss.SwitchExpression.SourceExpression, SourceResultType = nvar.CecilType } }; ss.SwitchExpression = nvexp.Clone(); ss.SwitchExpression.Parent = ss; asss.UpdateParents(); ss.PrependStatement(asss); return null; } } return el; }