예제 #1
0
        public FIRRTL.FirrtlNode GetDefNodeFromLowFirrtlGraph(string nodeName)
        {
            GraphFIR.Module lowFirMod = LowFirGraph.MainModule;

            string[] pathToModule = GetPathToCurrentActualModule();

            //Skip first module name as it's the name of the root node
            //that we start with
            foreach (var pathModName in pathToModule.Skip(1))
            {
                GraphFIR.FIRRTLNode[] lowModNodes     = lowFirMod.GetAllNodes();
                GraphFIR.FIRRTLNode   childLowModNode = lowModNodes.FirstOrDefault(x => x is GraphFIR.Module mod && mod.Name == pathModName);
                if (childLowModNode == null)
                {
                    throw new Exception("High level firrtl module path didn't match low level firrtl module path.");
                }

                lowFirMod = (GraphFIR.Module)childLowModNode;
            }

            //This is a meh way of going about getting the correct node.
            //Nodes by themselves don't have a name so it works on the assumption
            //that there exists an io with the name which points to the correct node.
            GraphFIR.IO.FIRIO nodeIO = (GraphFIR.IO.FIRIO)lowFirMod.GetIO(nodeName);
            return(nodeIO.Flatten().First().Node.FirDefNode);
        }
예제 #2
0
        private static List <FIRIO> CreateIO(FIRIO inputType, int addressWidth, FIRRTLNode node)
        {
            FIRIO dataOut = inputType.Flip(node);

            dataOut.SetName("rdata");

            FIRIO dataIn = inputType.Copy(node);

            dataIn.SetName("wdata");

            FIRIO mask = inputType.Copy(node);

            mask.SetName("wmask");
            AsMaskType(mask);

            List <FIRIO> io = new List <FIRIO>();

            io.Add(new Input(node, "wmode", new UIntType(1)));
            io.Add(dataOut);
            io.Add(dataIn);
            io.Add(mask);
            io.Add(new Input(node, "addr", new UIntType(addressWidth)));
            io.Add(new Input(node, "en", new UIntType(1)));
            io.Add(new Input(node, "clk", new ClockType()));

            return(io);
        }
예제 #3
0
 protected static void AsMaskType(FIRIO maskFrom)
 {
     foreach (ScalarIO scalar in maskFrom.Flatten())
     {
         scalar.SetType(new UIntType(1));
     }
 }
예제 #4
0
        public MemWritePort(FIRRTLNode node, string name, List <FIRIO> io) : base(node, name, io)
        {
            this.DataIn = (FIRIO)GetIO("data");
            this.Mask   = (FIRIO)GetIO("mask");

            InitDataToMask();
        }
예제 #5
0
        private static void ConnectIO(VisitHelper helper, GraphFIR.IO.FIRIO from, GraphFIR.IO.FIRIO to, bool isPartial, bool canBeConditional = true)
        {
            GraphFIR.Module fromMod = from.GetModResideIn();
            GraphFIR.Module toMod   = to.GetModResideIn();

            //If going from inside to outside or outside to outside
            //then add condition to that connection if currently in
            //conditional module.
            GraphFIR.IO.Output condition = null;
            if (canBeConditional &&
                ((fromMod == helper.Mod && toMod != helper.Mod) ||
                 (fromMod != helper.Mod && toMod != helper.Mod)))
            {
                condition = helper.Mod.EnableCon;
            }

            from.ConnectToInput(to, isPartial, false, condition);

            //If writing to a memory ports data in high level firrtl, then
            //the mask also has to be set to true for the part of the port data
            //that was written to.
            if (GraphFIR.IO.IOHelper.TryGetParentMemPort(to, out var memPort) &&
                memPort.FromHighLevelFIRRTL &&
                GraphFIR.IO.IOHelper.IsIOInMaskableMemPortData(to, memPort))
            {
                var scopeEnableCond = helper.ScopeEnabledCond;
                foreach (GraphFIR.IO.Input dataInputWrittenTo in to.Flatten())
                {
                    var dataInputMask = memPort.GetMaskFromDataInput(dataInputWrittenTo);
                    scopeEnableCond.ConnectToInput(dataInputMask, false, false, scopeEnableCond);
                }
            }
        }
예제 #6
0
        public MemRWPort(FIRRTLNode node, string name, List <FIRIO> io) : base(node, name, io)
        {
            this.DataOut   = (FIRIO)GetIO("rdata");
            this.DataIn    = (FIRIO)GetIO("wdata");
            this.Mask      = (FIRIO)GetIO("wmask");
            this.WriteMode = (FIRIO)GetIO("wmode");

            InitDataToMask();
        }
예제 #7
0
 public override void ConnectToInput(FIRIO input, bool allowPartial = false, bool asPassive = false, Output condition = null)
 {
     if (input is Input ioIn)
     {
         ioIn.Connect(this, condition);
         ConnectOnlyOutputSide(ioIn);
     }
     else
     {
         throw new Exception("Output can only be connected to input.");
     }
 }
예제 #8
0
        public Vector(FIRRTLNode node, string name, int length, FIRIO firIO) : base(node, name)
        {
            if (!firIO.IsPassive())
            {
                throw new Exception("IO type of vector must be passive.");
            }

            this.IO = new FIRIO[length];
            for (int i = 0; i < IO.Length; i++)
            {
                IO[i] = firIO.Copy(node);
                IO[i].SetName(i.ToString());
                IO[i].SetParentIO(this);
            }
        }
예제 #9
0
        private static void VisitConnect(VisitHelper helper, FIRRTL.Expression exprFrom, FIRRTL.Expression exprTo, bool isPartial)
        {
            GraphFIR.IO.FIRIO from = VisitExp(helper, exprFrom, GraphFIR.IO.IOGender.Male);
            GraphFIR.IO.FIRIO to   = (GraphFIR.IO.FIRIO)VisitRef(helper, exprTo, helper.Mod, GraphFIR.IO.IOGender.Female);

            //Can only connect two aggregates. If any of the two are not an
            //aggregate type then try convert both to scalar io and connect them.
            if (from is not GraphFIR.IO.AggregateIO || to is not GraphFIR.IO.AggregateIO)
            {
                from = from.GetOutput();
                to   = to.GetInput();
            }

            ConnectIO(helper, from, to, isPartial);
        }
예제 #10
0
        private static List <FIRIO> CreateIO(FIRIO inputType, int addressWidth, FIRRTLNode node)
        {
            FIRIO dataOut = inputType.Flip(node);

            dataOut.SetName("data");

            List <FIRIO> io = new List <FIRIO>();

            io.Add(dataOut);
            io.Add(new Input(node, "addr", new UIntType(addressWidth)));
            io.Add(new Input(node, "en", new UIntType(1)));
            io.Add(new Input(node, "clk", new ClockType()));

            return(io);
        }
예제 #11
0
        public override void ConnectToInput(FIRIO input, bool allowPartial = false, bool asPassive = false, Output condition = null)
        {
            if (input is not Vector)
            {
                throw new Exception("Vector can only connect to other vector.");
            }
            Vector other = (Vector)input;

            if (!allowPartial && Length != other.Length)
            {
                throw new Exception("Vectors must have the same when when fully connecting them.");
            }

            int shortestLength = Math.Min(Length, other.Length);

            for (int i = 0; i < shortestLength; i++)
            {
                IO[i].ConnectToInput(other.IO[i], allowPartial, asPassive, condition);
            }
        }
예제 #12
0
        private static GraphFIR.IO.FIRIO GetIOGender(VisitHelper helper, GraphFIR.IO.FIRIO io, GraphFIR.IO.IOGender gender)
        {
            if (io is GraphFIR.IO.Input input && gender == GraphFIR.IO.IOGender.Male)
            {
                string duplexOutputName = helper.Mod.GetDuplexOutputName(input);

                //Try see if it was already created
                if (input.GetModResideIn().TryGetIO(duplexOutputName, out var wireOut))
                {
                    return((GraphFIR.IO.Output)wireOut);
                }

                //Duplex output for this input wasn't created before so make it now.
                //Make it in the module that the input comes from so there won't
                //be multiple duplex inputs residing in different cond modules.
                return(input.GetModResideIn().AddDuplexOuputWire(input));
            }

            return(io.GetAsGender(gender));
        }
예제 #13
0
        public override void ConnectToInput(FIRIO input, bool allowPartial = false, bool asPassive = false, Output condition = null)
        {
            if (input is not IOBundle)
            {
                throw new Exception("Bundle can only connect to other bundle.");
            }
            IOBundle bundle = (IOBundle)input;

            if (asPassive && !IsPassiveOfType <Output>())
            {
                throw new Exception("Bundle must be a passive output bundle but it was not.");
            }

            if (asPassive && !bundle.IsPassiveOfType <Input>())
            {
                throw new Exception("Bundle must connect to a passive input bundle.");
            }

            if (!allowPartial && IO.Count != bundle.IO.Count)
            {
                throw new Exception("Trying to fully connect two bundles that don't match.");
            }

            IEnumerable <string> ioConnectNames = IO.Keys;

            if (allowPartial)
            {
                ioConnectNames = ioConnectNames.Intersect(bundle.IO.Keys);
            }

            foreach (var ioName in ioConnectNames)
            {
                var a = GetIO(ioName);
                var b = bundle.GetIO(ioName);

                if (a is Output aOut && b is Input bIn)
                {
                    aOut.ConnectToInput(bIn, allowPartial, asPassive, condition);
                }
예제 #14
0
        public string GetFullName()
        {
            List <string> pathToRoot = new List <string>();

            if (Name != null)
            {
                pathToRoot.Add(Name);
            }

            FIRIO node = this;

            while (node.ParentIO != null)
            {
                node = node.ParentIO;
                if (Name != null)
                {
                    pathToRoot.Add(node.Name);
                }
            }

            pathToRoot.Reverse();
            return(string.Join('.', pathToRoot));
        }
예제 #15
0
 public MemoryIO(FIRRTLNode node, string name, List <FIRIO> io, FIRIO inputType, int addressWidth) : this(node, name, io, inputType, addressWidth, new List <MemPort>())
 {
 }
예제 #16
0
 public MemReadPort(FIRRTLNode node, string name, List <FIRIO> io) : base(node, name, io)
 {
     this.DataOut = (FIRIO)GetIO("data");
 }
예제 #17
0
 public MemPort(FIRRTLNode node, string name, List <FIRIO> io) : base(node, name, io)
 {
     this.Address = (FIRIO)GetIO("addr");
     this.Enabled = (FIRIO)GetIO("en");
     this.Clock   = (FIRIO)GetIO("clk");
 }
예제 #18
0
        private static void VisitStatement(VisitHelper helper, FIRRTL.Statement statement)
        {
            if (statement is FIRRTL.EmptyStmt)
            {
                return;
            }
            else if (statement is FIRRTL.Block block)
            {
                for (int i = 0; i < block.Statements.Count; i++)
                {
                    VisitStatement(helper, block.Statements[i]);
                }
            }
            else if (statement is FIRRTL.Conditionally conditional)
            {
                VisitConditional(helper, conditional);
            }
            else if (statement is FIRRTL.Stop stop)
            {
                var clock  = (GraphFIR.IO.Output)VisitExp(helper, stop.Clk, GraphFIR.IO.IOGender.Male);
                var enable = (GraphFIR.IO.Output)VisitExp(helper, stop.Enabled, GraphFIR.IO.IOGender.Male);

                var firStop = new GraphFIR.FirStop(clock, enable, stop.Ret, stop);
                helper.AddNodeToModule(firStop);
            }
            else if (statement is FIRRTL.Attach)
            {
                return;

                throw new NotImplementedException();
            }
            else if (statement is FIRRTL.Print)
            {
                return;

                throw new NotImplementedException();
            }
            else if (statement is FIRRTL.Verification)
            {
                return;

                throw new NotImplementedException();
            }
            else if (statement is FIRRTL.Connect connect)
            {
                VisitConnect(helper, connect.Expr, connect.Loc, false);
            }
            else if (statement is FIRRTL.PartialConnect parConnected)
            {
                VisitConnect(helper, parConnected.Expr, parConnected.Loc, true);
            }
            else if (statement is FIRRTL.IsInvalid)
            {
                return;

                throw new NotImplementedException();
            }
            else if (statement is FIRRTL.CDefMemory cmem)
            {
                //If have access to low firrth graph then get memory definition
                //from it as it includes all port definitions. This avoids having
                //to infer memory port types.
                if (helper.HasLowFirGraph())
                {
                    var lowFirMem = (FIRRTL.DefMemory)helper.GetDefNodeFromLowFirrtlGraph(cmem.Name);
                    VisitStatement(helper, lowFirMem);

                    //Low level firrtl addresses the ports through the memory but
                    //high level firrtl directly addreses the ports. Need to
                    //make the ports directly addresseable which is why this is done.
                    var lowMem = (GraphFIR.IO.MemoryIO)helper.Mod.GetIO(cmem.Name);
                    foreach (GraphFIR.IO.MemPort port in lowMem.GetAllPorts())
                    {
                        port.FromHighLevelFIRRTL = true;
                        helper.Mod.AddMemoryPort(port);
                    }
                }
                else
                {
                    GraphFIR.IO.FIRIO inputType = VisitTypeAsPassive(helper, FIRRTL.Dir.Input, null, cmem.Type);
                    var memory = new GraphFIR.Memory(cmem.Name, inputType, cmem.Size, 0, 0, cmem.Ruw, cmem);

                    helper.AddNodeToModule(memory);
                }
            }
            else if (statement is FIRRTL.CDefMPort memPort)
            {
                var memory = (GraphFIR.IO.MemoryIO)helper.Mod.GetIO(memPort.Mem);

                //Port may already have been created if the memory used the low firrtl
                //memory definition which contain all ports that will be used
                GraphFIR.IO.MemPort port;
                if (memory.TryGetIO(memPort.Name, out var existingPort))
                {
                    port = (GraphFIR.IO.MemPort)existingPort;
                }
                else
                {
                    port = memPort.Direction switch
                    {
                        FIRRTL.MPortDir.MInfer => throw new NotImplementedException(),
                              FIRRTL.MPortDir.MRead => memory.AddReadPort(memPort.Name),
                              FIRRTL.MPortDir.MWrite => memory.AddWritePort(memPort.Name),
                              FIRRTL.MPortDir.MReadWrite => memory.AddReadWritePort(memPort.Name),
                              var error => throw new Exception($"Unknown memory port type. Type: {error}")
                    };

                    port.FromHighLevelFIRRTL = true;
                    helper.Mod.AddMemoryPort(port);
                }

                ConnectIO(helper, VisitExp(helper, memPort.Exps[0], GraphFIR.IO.IOGender.Male), port.Address, false);
                ConnectIO(helper, VisitExp(helper, memPort.Exps[1], GraphFIR.IO.IOGender.Male), port.Clock, false, false);
                ConnectIO(helper, helper.ScopeEnabledCond, port.Enabled, false);

                //if port has mask then by default set whole mask to true
                if (port.HasMask())
                {
                    GraphFIR.IO.FIRIO  mask   = port.GetMask();
                    GraphFIR.IO.Output const1 = (GraphFIR.IO.Output)VisitExp(helper, new FIRRTL.UIntLiteral(0, 1), GraphFIR.IO.IOGender.Male);
                    foreach (var maskInput in mask.Flatten())
                    {
                        ConnectIO(helper, const1, maskInput, false);
                    }
                }
            }
            else if (statement is FIRRTL.DefWire defWire)
            {
                GraphFIR.IO.FIRIO inputType = VisitTypeAsPassive(helper, FIRRTL.Dir.Output, null, defWire.Type);
                inputType = inputType.ToFlow(GraphFIR.IO.FlowChange.Sink, null);
                GraphFIR.Wire wire = new GraphFIR.Wire(defWire.Name, inputType, defWire);

                helper.AddNodeToModule(wire);
            }
            else if (statement is FIRRTL.DefRegister reg)
            {
                GraphFIR.IO.Output clock     = (GraphFIR.IO.Output)VisitExp(helper, reg.Clock, GraphFIR.IO.IOGender.Male);
                GraphFIR.IO.Output reset     = null;
                GraphFIR.IO.FIRIO  initValue = null;

                if (reg.HasResetAndInit())
                {
                    reset     = (GraphFIR.IO.Output)VisitExp(helper, reg.Reset, GraphFIR.IO.IOGender.Male);
                    initValue = VisitExp(helper, reg.Init, GraphFIR.IO.IOGender.Male);
                }

                GraphFIR.IO.FIRIO inputType = VisitTypeAsPassive(helper, FIRRTL.Dir.Input, null, reg.Type);
                GraphFIR.Register register  = new GraphFIR.Register(reg.Name, inputType, clock, reset, initValue, reg);
                helper.AddNodeToModule(register);
            }
            else if (statement is FIRRTL.DefInstance instance)
            {
                GraphFIR.Module mod = VisitModule(helper, instance.Name, helper.ModuleRoots[instance.Module]);
                helper.AddNodeToModule(mod);
            }
            else if (statement is FIRRTL.DefNode node)
            {
                var nodeOut = VisitExp(helper, node.Value, GraphFIR.IO.IOGender.Male);

                if (node.Value is not FIRRTL.RefLikeExpression)
                {
                    nodeOut.SetName(node.Name);
                }

                helper.Mod.AddIORename(node.Name, nodeOut);
            }
            else if (statement is FIRRTL.DefMemory mem)
            {
                GraphFIR.IO.FIRIO inputType = VisitTypeAsPassive(helper, FIRRTL.Dir.Input, null, mem.Type);
                var memory = new GraphFIR.Memory(mem.Name, inputType, mem.Depth, mem.ReadLatency, mem.WriteLatency, mem.Ruw, mem);

                foreach (var portName in mem.Readers)
                {
                    memory.AddReadPort(portName);
                }
                foreach (var portName in mem.Writers)
                {
                    memory.AddWritePort(portName);
                }
                foreach (var portName in mem.ReadWriters)
                {
                    memory.AddReadWritePort(portName);
                }

                helper.AddNodeToModule(memory);
            }
            else
            {
                throw new NotImplementedException();
            }
        }
예제 #19
0
 public override void ConnectToInput(FIRIO input, bool allowPartial = false, bool asPassive = false, Output condition = null)
 {
     throw new Exception("Input can't be connected to output. Flow is reversed.");
 }
예제 #20
0
 public override void ConnectToInput(FIRIO input, bool allowPartial = false, bool asPassive = false, Output condition = null)
 {
     throw new Exception("Duplex can't be connected to anything.");
 }
예제 #21
0
 public MemRWPort(FIRRTLNode node, FIRIO inputType, int addressWidth, string name) : this(node, name, CreateIO(inputType, addressWidth, node))
 {
 }
예제 #22
0
 private MemoryIO(FIRRTLNode node, string name, List <FIRIO> io, FIRIO inputType, int addressWidth, List <MemPort> ports) : base(node, name, io)
 {
     this.Ports        = ports;
     this.InputType    = inputType.Copy(null);
     this.AddressWidth = addressWidth;
 }
예제 #23
0
 public DuplexIO(FIRRTLNode node, string name, FIRIO inIO, FIRIO outIO) : base(node, name)
 {
     this.InIO  = inIO;
     this.OutIO = outIO;
 }