Yes, so I'm going to give a talk about building a product with Opti. So actually using Opti to build a product which you can deploy to production and be reasonably sure that nobody's going to leak your secrets, you deploy it into the product in the end. So a bit about me, my name is Ruben Zawinski. I work for Pengotronics ECHAR. We do a lot of embedded software consulting. So we do things like bought support packages, and we often work on embedded ARM platforms. You can find me on GitHub with the name EmanTor, and you can also contact me by email at this email address. At Pengotronics, I do a lot of work with Opti. I do a bit of system integration. So integrating Opti into the bought support package, which will eventually be used in the field. I also do a bit of testing because I wrote a testing framework like three years ago, which we still use today to test platforms when we eventually want to do updates on the platforms. Let's get short overview. So I'm going to start with a bit of introduction, a short introduction into the trust zone and Opti. Then I'm going to present a motivation for this talk. Then I'm going to show you the problems you run into when you're trying to use Opti in a product. I'm going to present the solutions so far for the platform I'm working on, but which should also be applicable to the platforms you may be working with. I'm going to come to a conclusion, and then there's going to be the happy outlook where I wish for things which are not implemented yet. So let's start with the trust zone. So trust zone in 32 bits divides our processor state into a normal world and a secure world, and then there's some kind of secure monitor which allows us to switch between the different worlds. So the usual CPUs come up in the secure world, then the bootloader starts up in the secure world. I deploy my trusted operating system, and the trusted operating system ensures that when it searches over to the normal world, my bootloader can continue to run. And every time I want to access some kind of trust zone data, or I want to call into my trusted operating system, I do this SMC called secure monitor call, which goes into the secure monitor. The secure monitor then does all the sanitization between the normal and the secure world, so ensuring no register contents are leaked and everything is sanitized, and then goes into the secure world. The secure world does some kind of computation. My trusted operating system runs my trusted application, which runs in the field, which also may compute some secrets, may request some pin entry from a secure device, whatever, and then returns the data back to the normal world. The trusted operating system we are employing in the field is called OPTI, which is the open portable trusted execution environment, and it's an open source implementation of the global platform T specifications, which use the trust zone. Global platform is a standard body, which also standardized smart card interfaces. So the idea is that you have a standard interface for your trusted applications, and then it doesn't matter which trusted operating system in the end you're going to use. OPTI also has support for various ARM platforms, so there's some support for STM32, TI platforms are supported, layerscape platforms from NXP are supported, and Broadcom platforms, for example, for simple development use cases, you can also use Raspberry Pis, so there's support for Raspberry Pi 3 to develop on OPTI there. And my focus is especially on IMX6 32-bit platforms, or specifically on IMX6-UL platforms. So the motivation for the talk is that we want to secure OPTI and the trusted applications running within OPTI for production use, so we want to be reasonably sure that we are not leaking our data and production anywhere, and we want to ensure that upstream OPTI can be used securely on IMX6, so all the changes I need to do to OPTI are not going to live downstream somewhere, so they're going to go upstream into the project, so we don't have to maintain that and can do that in conjunction with the upstream OPTI maintainers. And I also want to provide some guidance which parts may be missing for other platforms, because I'm specifically looking at IMX6 platforms, I don't know how to implement certain parts for TI or STM platforms and how to solve certain problems there, but I can show you the problems and maybe you can come up with a solution to the problem. So the problems are, which components do I need to secure OPTI? So which are the parts which need to be implemented by the platform, rather than by the OPTI core to secure the OPTI in production, and which part of this configuration is already done upstream? So what's the part that I don't need to worry about, which part has already been done by the upstream maintainers, or maybe by the SOC manufacturer who upstreamed his changes to upstream OPTI? And then again, the next question is, which parts of this needs to be managed by the system integrator? So which part needs to be managed by the person who in the end is going to assemble the whole system, including the kernel, including the bootloader, and including the trusted operating system? So securing upstream OPTI, from my point of view, consists of the following five or optionally six points. You need to employ some kind of RAM protection, or you need to employ the OPTI pager. You need a hardware unique key for your platform. You need to see the OPTI pseudo random number generator with a sufficiently random seed. You need some kind of peripheral access configuration, depending on your platform. And you have to ensure that you have a trusted bootup of your OPTI operating system. So you need to ensure that only the OPTIs you compiled can boot on the platform, because otherwise somebody could run other OPTIs and thus leak your secrets on the platform. And you optionally want to employ some kind of storage rollback protection to ensure that nobody can fool you with old data from a previous installation. So let's start with the RAM protection. So the one thing you can do for RAM protection is employ some kind of DDR firewall. And this protects part of my RAM from access by the normal world. So an example of this is the trust zone controller 380 hardware which supports the configuration of multiple regions. So you can say, I'd like to be 32 megabytes at the very end of RAM to be allocated to the secure world, and the normal world can no longer access the memory there. Every time the normal world will try to access this memory, it will generate an interrupt to notify you that somebody tried to access the secure memory from the normal world, and you will also read only zeros from the normal world. And for IMX6 platforms, there's this trust zone address space controller from ARM used inside the platform. So many SOCs may use different DDR firewalls. There are also custom implementations from different vendors. I know that, for example, the high key platforms use a custom DDR firewall which is not very well documented as far as I know, or the documentation is hard to get to. But for these ARM standard implementations, you can just download the datasheet from ARM. And the upstream, there's already an upstream driver for these trust zone controllers inside of Opti. And you had to previously describe the regions and all the stuff yourself, but this is no longer necessary because, depending on your platform configuration for IMX6 platforms, at least, there's auto configuration. So with an Opti, we already know the total memory size. We already know how much memory we want in the secure world. And we can just calculate how the region configuration inside this trust zone controller should look like. And then we can just apply the trust zone controller configuration and be happy that nobody can access this. It's also important to remember that there may be some kind of bypass for this trust zone controller. For IMX6 platforms, as an example, there's a single bit in the IOMUX which you need to set to disable the bypass of the trust zone controller because you have a certain bandwidth. So there's a small reduction of bandwidth going through the DDR firewall. And you have to disable this, obviously, because otherwise you can just bypass the firewall and everybody can read your secure world memory, which is rather bad. So next up, an alternative to using this run protection or configuring the DDR firewall is employing the Opti pager, where you run a small part of your Opti inside the SRAM on your CPU and then you encrypt all the other memory pages you want to store into a normal memory. You still want to ensure that nobody can overwrite the memory in the end. But even if they can read the memory, the memory is still going to be encrypted and authenticated, which does not necessarily require the DDR firewall. There are some constraints with this. Your device needs to have a sufficient amount of SRAM, so 128 kilobytes to 256 kilobytes. And for us, the chosen IMX6-UL does not necessarily have enough SRAM, depending on the version of the processor you select. And also for bigger variants which may have enough SRAM, there's constraints on other devices maybe requiring the SRAM. So even for this IMX6-UL, there's a pixel co-processor you can use to do simple frame buffer stuff or simple 2D graphics on an external display. And this requires 128 times 32 bits of SRAM to store the frame buffers for your pixel pipeline. So if you connect the display, your SRAM is going to be smaller. And for bigger IMX6 variants, there's the image processing unit or the GPU which also may require SRAM to store data because DDR memory may be too slow for this. So this was why we didn't choose the OptiPager as the way to go there and instead use the DDR firewall. So next up is this hardware-unit key. Opti requires some kind of hardware-unit key which is used to derive all the other keys on bootup. And this should be a unique per device which means that every device should have a unique key and subsequently once a device stores data it can only be decrypted by the very same processor. And obviously it should not be accessible from the normal world because otherwise people can just derive the key in the normal world and decrypt the data. For IMX6 we actually use a trick with the cryptographic acceleration and authentication module. There's something called the master key verification blob where you can say I want to do a hash over the master key which is unique per device and then we use this hash as the hardware-unit key. And additionally in the calm there's a bit where you can log out this generation or where you can increment a counter and the next one who does this master key verification blob is going to get a different hash. And you are never going to get the same hash again unless you reboot the platform and then the bit is unset again. And this is still not in upstream Opti. The pull request at the moment is closed because this needs to be rebased on the IMX6 7 calm driver. So NXP actually contributed a driver for the calm. The calm does more than this master key verification blob. You can also do AAS encryption and decryption in hardware. So a lot of crypto acceleration is possible there. It also does hash algorithms. And I'm currently in the process of rebasing this on the calm driver and then we should have hardware-unit key derivation for Opti platforms or for IMX6 platforms. So this will be done soon. Then the next one is RNG seeding. So Opti internally if you use a software RNG you can also use a hardware RNG but due to constraints on our platforms we don't want to use the hardware RNG. You still require some kind of RNG seed. And the default seed for a development environment is always zero. So it's kind of well predictable. That's not necessarily what you want for a product. So for IMX6 we have an RNG or true random number generator again inside this calm block and we can read out a seed for our pseudo random number generator at the very beginning of boot and then just seed the PRNG with this. And this is not implemented yet. It's up on my schedule. I'll get to it at some point and then we should have good RNG seeding at the start of Opti. I know currently if you start Opti on IMX6 platform it's also going to complain with a loud warning saying seeding RNG with zero's exclamation mark. So eventually I'd like to get rid of this and do real RNG seeding. So there's also the problem of peripheral access configuration. So SOCs have DMA masters usually besides the CPU and the DDR firewall only protects you from accesses which are marked as normal. So if they are marked as a secure world access your DDR firewall is just going to let the access through. And depending on how your platform works those masters may actually be default secure. So in the end I configure my DDR firewall correct. I configure my bypass correct. So my CPU normal world process can't access my secure memory which is great. But then I asked the GPU hey give me a DMA transfer from my secure memory and the GPU says happily here's your DMA transfer what else do you want. So you need to ensure that all masters are configured as non-secure and this is highly dependent on your platform. So read your reference manual and ensure that these access policies are configured correctly. For IMX6 there's a unit inside the processor which is called the central security unit CSU. There's a register inside of it where you can just say whether this DMA master is secure or non-secure and for this we just configure everything as non-secure except for the CPU obviously. And then everything is safe. If you want to do some kind of peripheral access from opti however then it gets more interesting.  We just configure everything default non-secure inside the IMX6 URL. And it's rather trivial to configure this register because on your platforms you just have to look inside the security reference manual and then find out which peripherals are actually on your specific SOC and then submit this should be really, really easy. And then next is trusted boot up. So you have to use your platform's version of verified or secure boot because otherwise anybody could start other opti versions on your board and then just leak your secrets and then verify it and this verifies the opti version to prevent replacements. So for IMX6 platforms there's a high assurance boot implemented by the SOC vendor and inside the boot ROM. So the boot ROM verifies our boot loader. The boot loader in turn contains a binary version of opti so the boot loader is verified, the opti is verified and the very first thing the boot loader starts on startup is opti. We try to minimize the attack vector in this case. And this is not something you can implement in upstream opti. This is something you need to ensure on the integration level. So inside this is something the system integrator has to do when he's designing the platform. So not only does he need to compile the kernel, compile the boot loader, compile the opti and bundle it all into a fine bundle. He also needs to enable high assurance boot on the SOC and sign the boot loader and opti correctly. And then he may also want to sign his user space and the Linux kernel to ensure that there's no untrusted software running on the SOC. If you're added, why not do that as well? And then there's also optionally storage rollback protection. You can use the EMMC feature of replay protected memory blocks which is an area where your writes are replay protected by a counter. Opti implements this as a simple FAT file system. So many MMCs have a replay protected memory block size of like four megabytes which is enough to store some kind of data or store an encryption key for data as an example. And this is already supported upstream. So you have to enable this replay protected memory block file system and then you have to deploy this one time during production to write a key or to exchange a key between your processor and your EMMC. And this is a one-time operation. You can't write this key again. This is then kind of fused to your EMMC.  And you also have to ensure to disable the emulation in the user space program which facilitates the communication to user space from the kernel side because otherwise this provides an emulation layer to test this in a development environment. But for production devices, obviously you want to disable this. So in conclusion, there's no platform which is totally secure at the moment in upstream opti. I'm slowly getting EMMC 6 to a state where I can say if you enable the correct switches and ensure that you use high assurance boot your opti should be secure enough. And vendor implementations may include the necessary bits. So because opti is a BSD 2 clause licensed downstream vendors do not necessarily have to open source the implementations. But sometimes you can bug them or sometimes they release them as well and then you can look at their implementations. But you still have to review all the code they implemented and get the reference manual and then cross-reference between the implementation and what the reference manual says. And even then you have to sometimes test whether their implementation works correctly. In the end you have to get a real hardware platform. You have to do all the different stuff and then actually test whether your memory accesses are now protected or whether your DMA masters can now really not access the secure word memory. So it requires a lot of validation and testing on your side. And then I'll get to the outlook or wish list. So currently we have a certain problem in that clock accesses and coordination between opti and Linux is kind of hard. I told you before that this cryptographic acceleration and assurance module is now supported with an opti. But the kernel may disable the clocks for your cryptographic module because the kernel is managing the clocks on the system. And if you try to access the crypto module in opti because your TA wants to encrypt some kind of data your platform is just going to get stuck because there's a transaction on the bus but nobody is sending it. So you effectively have a denial of service attack there. And I would like some kind of fix or some kind of framework for this. There's some work ongoing but I think it targets more ARM 64 bit platforms but I'll have to look into this again. And I also would like deeper device integration for opti. So currently it's a lot of platform device definitions with an opti and there's not much parsing of device tree information going on. The device tree is basically just used to insert some properties for Linux to parse so Linux knows that opti is available but stuff like memory sizes or available peripherals can all be passed from the device tree and opti already includes the possibility to include a device tree within opti itself. So in theory you could do all the probing of devices from the device tree as it's done with in Linux at the moment. And I would also like some more CI infrastructure to test each commit to opti master for iMix 6 because on the way here I tried to test the latest release which was like a week ago but unfortunately there was a last minute fix going in and my platform doesn't boot at the moment on the latest release. So obviously we need some kind of CI there and I need to allocate some time to get platforms up and running to ensure that the platforms don't get broken again. Yeah, so that's the talk and now I'd like to answer your questions. Yes please. The firewalls always spoke about the firewall for opti, but is it also provisional? Yes, so for iMix 6 platforms there's only this DDR firewall that STM platforms have a very have a more advanced method of assigning peripherals to the secure or normal world or the small cortex co-processor and I'm not entirely sure but I think there's a framework being talked about on how to coordinate this. Yes please. Figured by the people building the product and I was wondering yes this is so all the configuration needs to be done at build time and in the case of this replay protected memory blocks thing you also need two opti binaries so you need one opti binary which is basically configured the same as the other one but includes this right key provisioning so it actually exchanges the key between the CPU and the EMMC for manufacturing use. So during manufacturing you would write the key and then afterwards deploy your normal opti which no longer does the key exchange so the key doesn't leak. Yes, Ahmed. Yes, and you know there's some implementation discussion currently going on for opti but I have not looked deeply into it yet. Other questions, yes. No, I did not yet. I just got this merged like two days ago or three days ago when I did the talk and I still have to verify that these DMA accesses are now forbidden. I will probably just hack the GPU driver to try and ask DMA request but you could also probably do it using the URDMA capability so the SDMA firmware should be able to do DMA transfers there. So I will test this and then I will submit more pull requests to fix this if it doesn't work. No, I unfortunately don't have open PCIe ports on the IMX6UL it's too small for that but that would be a possibility on bigger platforms like IMX6Quat which has a PCIe port. Yeah. Other questions? Yeah. It's a part of the SOC in the system itself. It lives on the bus of the CPU.


First on the list, we have Aaron Friedman, who just finished his Master's of Computer Science in the field of Computational Geometry, and he is a Python developer working at Fabric, formerly known as Common Sense Robotics, involved in system architecture and development, and he's going to be talking about boosting simulation performance with Python. So, Aaron, thank you for joining us. Thank you for having me. Thank you for the introduction. So where are you streaming from? Sorry? Where are you streaming from? Oh, okay, I'm from Tel Aviv, Israel. Nice. Yeah. Excellent. How's the weather there? Really hot. Really hot. It's cool, yeah. Excellent. Well, I will turn this over to you, then. Okay. Thank you very much, and show the screen. Okay, so hi again, everyone, and thank you for being here. You're probably here because you run any kind of simulation or integration test at your work. Now, how many of you would like to spend less time on waiting for them to finish and to have more time for coding or for solving bugs if you write some? So I'm glad you're here. Today you will see how you can use the discrete event simulation approach to simulate your system. And now it will allow you to simulate hours of your system in minutes or even in seconds. So before I talk about how we run our simulation, let me tell you what we do in the fabric and what we simulate. Before I show you the video, I need to switch the sharing mode. Okay. We build a fulfillment warehouse for online orders. Most of the work is done by robots. We have two types of robots. The first type is called leaf robot. You can see it now in the video. And the second type is called ground robot, which moves on the ground on the floor. Together they cooperate and help us to fulfill the orders. And it works like that. The leaf robot takes thoughts from the shelving units would put the thought on the ground robot. The ground robot brings the thought into picking stations where the items are picked and later delivered to the customers. So my name is Iran. I work at fabric for about four years. Now I mainly focus on the development of this cute robot, but before that I was involved in different areas in the system. This is the simulation infrastructure, which I will present to you today. We start by seeing why simulations are so important. Then we'll see how to use the discrete event simulation approach and how to do it in Python. Then I'll talk about some challenges we encountered and how we deal with them. And finally how to distribute the multi-traded simulation into a multi-process simulation. So first, what exactly we simulate. Usually the term simulation means a tool that imitates the behavior of a system. Now a case it is not exactly the case. Let's take a look in this very simplified role of our system. We have the backend which is pure software. It manages the activity of the system. It manages the orders from clients, the stock, the motion of the robot. It sends commands to the robot and receives telemeters back from the robot. So in this simulation tool that I will talk about, we simulate only the robots. We run the system, the backend just as it runs in production, but instead of communicating with the real robot, it communicates with virtual robots. This, the copying of software and hardware is extremely important today when we all work from home due to the coronavirus and the access to the hardware is very limited. This tool, as several more you suggest, first it is used as a testing tool when developer write new code as long as the code doesn't run on the robot. Then it is one of the options to test the code. It is also used as part of our regression testing, the continuous integration system. Also in a complex system, it's difficult to know how a new algorithm or optimization will affect the system, the KPIs of the system. So this is the place to evaluate it before running it in production. Again, robots and the hardware is very limited and very extensive. This decoupling of software and hardware allows us to run as many simulations as we need on the cloud. We use this tool to evaluate a new warehouse before investing money in construction. We can run the system on a new layout and see what KPIs we can reach and how many robots are needed to reach this KPIs, for example. The simulation is very easy to inject fellows in the robots and by that to improve the reliability and robustness of the system. We also have an integration center in our offices and integration lab in our offices where we can test the code with the robots, but it's not as big as the production warehouse. So simulation is the only place you can run it on big setups before running it in the production. We saw what we simulate and what usage we do with this simulation tool. Now let's talk about how we run the simulation. The approach we are using is called discrete event simulation. This approach, continuous operations are modeled by instant events. For example, if we want to simulate an elevator, then the events can be door is open, elevator right, button pressed and so on. The simulation also maintains its own clock and it immediately moves from one event to the next event and that's how the time can run faster than the real time. In our simulation, we do it a little bit different. We treat the time as the events. In each, we divide the time into time peaks and each time we calculate the new state of the robots. We simulate the operations of the robot, which are move, turning, passing thought from one robot to another robot. Let's take an example. Let's see the move operation of the robot. Let's say that the robot can move in two meters per second and we choose to have 10 time peaks in a second. So at first the robot is located at X zero and assuming it got a move operation, then the next time it will be 0.1 and the robot will calculate the new state, which is 20 centimeters. Then again, the next time it could be in 0.2 and the robot will calculate the new location, which is 40 centimeters. I noticed that in this approach, the robot was never between 20 to 40 centimeters. It immediately moves from one state to the next. In reality, the robot anyway sends telemetrys to our backend few times in a second. So the behavior looks the same for the backend, which is discrete anyway, and we don't lose any information by doing so. So this is the idea of the discrete event simulation. Now to implement it in Python, we use the SimPy library. SimPy is an open source library. It is a framework for discrete event simulation. It's very simple and well documented and there's a lot of samples on the web. It is also lightweight. I mean that it doesn't try to help you to simulate your components. It just gives you the framework to implement the discrete event simulation. Before we see how to do it in the code, let's see, let's understand the idea of SimPy. So to understand SimPy, you need to be familiar with the three objects. The first one is environment, the second one is process, and the third one is the event. The environment is the main object that manage the world simulation. It has the simulation clock and it has an event queue. Process represents the component we want to simulate. So in this example we have two processes, one for robot zero and one for robot one. Now at first the processes adds the initial event in the queue. So we have two events, one for robot zero and one for robot one. So we start the environment, it takes the first event from the queue to transit. So it calculates the new state of the robot. And before it is done it adds the next event of that robot in the queue. And then again it takes the first event from the queue, which now belongs to robot one. Again calculates the new state, adds the next state of robot one in the queue. And then again it will take the next event from the queue. This is the time which again belongs to robot zero, but this time it is in time 0.1. So it will update the clock to 0.1. So this is the very basic idea of how SimPy works. Now let's see how to do it in the code. So in the code you'll see a very simple example of using the SimPy. In this example we'll conduct a race of robots. So let's say that a robot can move somewhere between two to four meters. Okay so let's go over the code and then we also will run it. So here we defined that we have three robots in the race. The race is going to last for 30 seconds and we choose to add two time ticks in a second. So we'll have a time tick after every half a second. Here we implement a very simple robot, we only implement the move operation. You can see it is a Python generator. So at first all the locations of the robot is zero. Each iteration of the while is a time tick. So it will calculate the new location to make it interesting to use the running function. Notice that I provide the function one and two because we said that the robot moves between two to four meters and we have two time ticks in a second. So it is one to two half a second. So the robot will print the simulation time, the robot ID and the new location. And it will tell the environment that the next time it wants to run is in half a second. So here we initialize our environment, we register the simple process into the environment and run the environment. Let's now run the race. So I have to run the code. Remember that the race is about 30 seconds and of course it is not going to take 30 seconds. I use the time command which will print the time it took the program to run. So as you can see it lasted less than one second. So I saved each of you 20 about 29 seconds. Okay, so an important point to be aware of is that all the simple process of the components are simulating running the same thread. As you could see, it is using Python generator and the environment runs each event at the time, and I will talk about it again in few slides. So all the parameters that affect the runtime of the simulation are obviously the number of components. The more components we are simulating than the more calculations we have to do, therefore slower simulation. And also the time to granularity, the bigger granularity than again more calculation in a second and the slower simulation. The mode I described so far is called as fast as possible. It means that the simulation price to run the fastest it can immediately move from one event to the next event. Simpy also allows to run in a real time mode where it tries to follow the real time it will run an event and before moving to the next event to wait until the time of the next event will come. Now, why would we want to do this? I mean, in the first thought you would think that we always want to run the fastest we can. But you may want to do some manual testing in your system like a REST score or whatever, or you also may want to combine real hardware with your simulation. So these are good reasons to run it in a real time mode. Declining the discrete event simulation approach has several benefits. The most obvious one is that it makes the development more efficient. When the developer finished write code and test it, then you will get a faster feedback. And also you get a shorter CI. But as you can imagine from the previous slide when I talked about parameters that affect the runtime, if we will run the simulation with many, many robots, then it may be that the simulation will even run slower than the real time. But this is still an advantage because that way the result of the simulation API will still be realistic. I mean that in every time tick all the robot will get the chance to do the calculations to calculate the new state. And that's how the time will not run too fast. And from the same reason is also deterministic. It doesn't matter if you run it on a strong machine on the cloud or on your private laptop. The runtime of the simulation may be affected but the result will be deterministic. And also it is agnostic to profiling and debugging. Still we will get the same results. Last, using this approach will also allow you very easy to simulate any date or any time of the day. Like you can run the system like it is the weekend or any special time that is interesting for you. In SimPy for example, you just need to provide the initial time to the environment and it is that simple. And then this bug wouldn't happen if we wouldn't be panicked before the millennium bug if we had this approach. Okay, so far I showed you how to simulate robots using the disk event simulation. But we called it at the beginning. I mentioned that we want to run our system, our backend together with the simulated robots. So our backend is a multi-treaded system. It has several threads that get messages and react to them. The messages can be either telemeters from robots, inputs from the user, and orders from customers and such. Can you think what is the problem of running the backend together with the robots? So the problem is that the robots may run the time too fast and the backend wouldn't have the time to do the work like it would do in the real time. SimPy has the support for event-driven processes. As I mentioned before, all the SimPy processes run in the single thread. So it will change the behavior of our backend and we already had a similar experience when we used the event monkey patch which makes your system your thread cooperative and runs the system like it is one thread. It did improve the performance of the system, but later we found out that we have some bugs that we couldn't see in simulation. Therefore, the solution of SimPy for event-driven processes is not good enough for us. So we came up with our own solution. In simulation, we create another SimPy process which in every time tick, it holds the time until the event-driven threads will do their work. It is doing it by calling the join on the threads queue and the join function waits until the queue is getting empty. And that's how you make sure that the event-driven thread will have the time to handle the events. Let's see an example in the code. Okay, so in this example, we'll see we'll have one event-driven thread which listened to the queue, got a message and printed it to the screen. Another robot which in every time tick will send a message to the event-driven thread. So let's go over the code. This time we'll have a time-tick, one time-tick in every one second. For now, I'll just show you the problem so ignore this class. We'll see it later. So this is a simple implementation of an event-driven thread. What it is doing is listening to the queue, printing the message to the screen, and that's it. Here we implement another simple robot. In each iteration, it adds a message in the event-driven queue. It gives the counter and tests the environment that will run again in one second. So again, we initialize the environment. Now it's time to see the problem. We use the regular Python queue. We start the event-driven thread. We register the environment and run it. So let's run it. So just remember, we are going to run the simulation for 50 seconds. And in each second, the robot will send a message to the event-driven thread which should print it to the screen. So run it. We don't see any message in the screen, and this is exactly the problem that I described. The robot did send 50 messages, but the event-driven thread didn't have the time to render them. So let's see how we solve it. We narrowed it from the Python queue, and in simulation, we had another simple process. In each time tick, it will call the join on the queue. And then we will again tell the environment that will run again in one second in the next time tick. So let's use this queue this time. So let's run the example again. This time with our queue. And as you can see, it solved the problem. The usage of the join helps the event-driven thread to handle the messages. So as you could see in the example, the event-driven thread is not really aware of SIMPAI. And that's what I meant that we run our backend in simulation just as it runs in production. It doesn't aware of whether it is a production or a simulation. With the extension that the backend cannot call the default time functionality because in simulation, they are not relevant, right? So we have to run the log. So you have all that functionality in our own module and the backend just calls this module. And this module knows whether it is simulation or production and calls the right functions. Last, we in simulation, we print the simulation time in the log because when you are debugging the simulation, you care more about the simulation time. Now, eventually, we also move to microservices, just like everyone else. And again, we wanted the simulation to run the simulation just like it runs in production. So it means that this time we don't use a multi-treaded simulation, but we want to distribute the simulation. We said that SIMPAI doesn't support a multi-treaded simulation, so for sure it doesn't support multiprocess simulation. So we came up with that solution. In a simulation, we run another service called the barrier server. And the responsibility of this service is to sync the time of the other services to prevent one service to run faster than the other services. So all the other services look the same as I described so far, the same as the multi-treaded simulation. Each one of them has its own local SIMPAI. And all of them pick a shared time tick. And it works like that. At the beginning, they initialize the SIMPAI, they do each service is doing his work. And once the shared time tick arrived, they send the ready message to the barrier service. The barrier service holds that message until it gets the message from all the other services. And once you got them, you send them the approval and then they can move to the next time tick. That's how we prevent one service to run faster from the other services. Notice that SIMSA service sends the ready message to the barrier server until it gets the approval. The time holds for me. Wait for the other services to reach the next time too. So I finished the slides. I think we have a few minutes for questions and then just sum up. Awesome. Thank you very much. So I do have a couple of why I have one question so far. If anyone has any questions, please post it in the Q&A here on zoom or you can also post it in the parrot track chat room over on discord, which I'm keeping an eye on as well. Anyway, so Ruth Vanderham asks, are you familiar with the other Python DES called Salabim? Yeah, I heard about it. I think it is quite new, maybe 2017. So before we started, it wasn't exist. But anyway, I checked it. It looks pretty similar to SIMPA. I think it also uses generators. And it has also the notion of an environment, I think. But anyway, I didn't really try to really use the SIMPA. And I also didn't see much comparisons. So if someone is familiar with it, I would like to hear in the discord system. I also have another question actually also from Ruth Vanderham. He says, how does the messaging between the barrier service work? So this is a depends on your implementation. So how your services communicate? In our case, we use a message queue for this. But you can do it with the rest or sockets or any other messaging. All right, excellent. So it looks like that's all I have at the moment. So once again, thank you very much. And yeah, if anyone wants to chat with Aaron afterwards, he is looked up his room, which I believe is boosting SIMP performance in discord. And Aaron, do you want to do a quick recap? Yeah, of course. Thank you. So yeah, so what we saw in the talk, we saw just how important the simulation is, especially for an hardware company like ours. And the disk event simulation has some more benefits with it. And again, if you want to do it in SimPy, in Python, you can do it in SimPy. Also, there is the Albin module library. If you want to run the simulation with your system, then you may suffer a time leak. You just need to make sure that all the components are tied to the time somehow to the clock. And then finally, the extension of the simulation into a distributed simulation was really straightforward for us. It really took us a couple of days to do it. So that's it. Thank you very much for listening. Okay, enjoy.


Hello and welcome. This video is part of a series. Be sure to check out the link in the description for the full playlist. Gonna try to go through this quickly. I'm gonna use Vim as my text editor. Use whatever editor you prefer. We are going to go into our code. Right now I'm calling it math.c. We have our basic C program up here with our main function and returning of zero. We're gonna do some basic math today. We're gonna create an integer we'll call a and we'll say that's equal to we'll say 6 and we'll say b equals 2 and then we're gonna create another integer down here we'll say c and we'll say that c equals a plus b and then we can use printf to print that out and what we're gonna do here is we're gonna say percent d since this is a number here we're gonna say our new line character and now here we want what number do we want to print we want print a we want print b we want print c here we'll say c so go ahead and do that and we'll compile it using gcc we'll say our math c input and then our output will just call math as our new executable dot slash saying running a command that's in this current directory called math run that and outputs 8 we can come in here and we can be we can change that if we want to instead of add we can multiply recompile it run it again we got 12 we can we can add or we just did add we can divide run that so six divide by two is three and we can also subtract we haven't done that yet right and run it again for so that's that's basic math let's go ahead and add a little bit more to this let's go ahead and change this back to just plus and let's go ahead and say percent d plus percent d equals percent d new line then here we'll do a comma and b so again these little placeholders here this is going to be replaced by whatever a is valued at this will be replaced whatever b is valued at and this will be replaced by whatever c is valued at so we can change the variables up here and I'll change it down there we should be able to compile that and I wrote something oh I forgot a comma there should be a comma right here let's go ahead and compile that again clear the screen and run it again and there we go 2 plus 6 equals 8 great let's see how long is this video we can keep ongoing let's go ahead and get the user input now we've used in the past we looked at gets which you really shouldn't use in f gets those are getting strings we want to get a numeric value you here so we're going to go up here let's go ahead and create these variables but leave them blank and what I'm going to do here is I'm going to say print f and I'm going to say enter to integers okay so we're going to get to basically kind of whole numbers here and we're going to use scan f and we're going to get two of those integers so we're going to say percent d and percent d and we're going to say that we are going to put those in I'm going to say dollar sign a comma dollar sign not dollar sign it's a dollar sign I meant ampersand ampersand b okay so now we're going to get that input from a user it's going to wait for two integers so I should be able to now recompile that and run it again it's going to ask for two integers and I can say one and two and it says one plus two equals three I can run again I can say three and six I can run again I can say 23 and 87 and does the math for me and it will also look for I can do this I can say two I can hit enter and still waiting for that second integer I can say 76 and does the math for me and if I was to give it three integers it only looks at those first two so that is some basic math there for you with grabbing the integers from the user let's go ahead and look at that again we're using scan f for this for getting those digits those integers from the user so I hope you found that useful as always please visit filmsbychrist.com that's Chris the K there should be a link in the description there you can search through my videos some of my software my scripting notes and if you like my videos you can always support me either a one-time donation with PayPal here or you can become a support over at patreon.com forward slash malix 1000 there's links to all of this in the links to this video or the description of this video as well as a link to this project here getlab.com forward slash malix 1000 forward slash my bin capital M capital B and if you look under the C folder there tutorials there are scripts that go along with this whole series I do thank you for watching and as always I hope that you have a great day


Hi, I'm Stella McQuarter and I am a 2020-2021 4-H state ambassador from Cleveland County and today I'm conducting a career interview with Mr. Jay Groves of Ray Lynn Construction. My name is Jay Groves with Ray Lynn. Okay, so Mr. Groves, the first question I want to ask you is what was your major in college? My major in college was building science at Auburn University and I graduated in 2002. Okay, and what is a day like in your role and what is your role? My role is we, well I started with Ray Lynn in 2002 when I graduated and so I'm about to begin my 19th year with them. We're based out of Carrollton, Georgia and I spent the large portion of my career working in and around Georgia and in 2015 they let me open up an office in Oxford, Alabama where I serve as the vice president of the Alabama division. We just manage all the construction projects within the state of Alabama. Alright, what would you say is the best thing about your job? The best thing about my job is there is never a dull moment. There is no getting bored with what you're doing in the construction industry because every day is a different challenge. Every hour is a different challenge so there's no complacency in the construction industry. Okay, what kind of problems do you face in your line of work? Well, as within any line of work there's always challenges. I guess the biggest challenge we have to face is basically taking a set of documents that an architect would draw in two dimensions and actually put that document to work in vertical construction and with all the challenges you're faced with conflicts of mechanical electrical plumbing, making everything work because just because an architect draws it doesn't always mean that it can be done the way they draw it. The other challenge is the environment you're working in because in construction you cannot control the weather so weather is a huge challenge. The other challenge we have in our industry as with a lot of industries is the availability of skilled manpower and skilled manpower is steadily declining and has been declining in just my 19 years. What kind of hours do you work? Long hours, lots of hours. Usually speaking the construction work day is generally a 7 to 330 work day but when you're in leadership role you're basically on call at all times so our biggest tool is our phone obviously and at that phone is on we are typically on call and working because questions get answered and questions get asked and answered before hours and after hours. What do you think has been your greatest success in your career? The greatest success in my career, you know every project has its own set of successes. Every project seeing it from start to finish is very rewarding but to pick out a single project that's been the most successful would be pretty difficult. Probably the most fun project I ever did was the University of West Georgia Athletic Complex. That was probably the most enjoyable project that I did. Could you tell us some other projects that you have worked on? When I got out of school my first project out of school was in Blue Ridge, Georgia built a performing arts center and a gymnasium in Blue Ridge up in the Blue Ridge Mountains and from there I went to Albany, Georgia and built about a 200,000 square foot school right north of Albany in Dawson, Georgia and from there I went to Rome, Georgia and built a lot of schools in Rome and spent about three years in Savannah, Georgia did four projects down in the low country of Georgia and did some other projects in Rome, did some projects, did the West Georgia Project in Carrollton, Georgia and then basically opened the office in Alabama and worked mainly all over East Central Alabama, northeast in East Central Alabama the last five years. What advice would you give someone interested in your profession? Stay focused, work hard and have a good attitude. It's not rocket science what we do, it's not difficult from the X's and O's standpoint of it but it is a very demanding profession. It can be very stressful at times but it does have a lot of rewards associated with it but I would submit that if you keep a good attitude and the work ethic is there and when I say that work ethic has to be there it's not for leadership people in the construction industry is not a seven to three thirty job it's a um there's lots of 10 to 12 hour days so um so yeah I would just say work hard stay focused and keep a good attitude. All right those are all the questions I have for you if you have anything else you'd like to tell us because it's not. I think you need to think very strongly about going into some sort of the construction industry I think you'd be a big asset. I'm very interested, this is why I wanted to interview you. Well I appreciate you interviewing me.