That was in 1978 and the computer was an Apple II.
I admit I struggled with QM.
Digital circuits use a fairly simple model, and that's not difficult to pick up.
Analog circuits can use a number of more complex models, and they're more of a challenge, depending on what you're trying to do.
Actually designing transistors - defining dopant levels, topology, and process steps - is a very specialised skill that very few people have.
And modern PC motherboards are marvels of electromagnetic engineering as well as electronic engineering. You have GHz signals running reliably on circuit boards with multiple layers. Getting those to work is another very specialised skill.
So it would quite something to find someone who had a professional-level understanding of all the levels: from silicon chemistry and quantum physics at one extreme, to electromagnetic design, to all the different levels of electronic design, to binary machine language and processor architectures, to OS design and application software, to all the various data structures and encodings that make all of the above useful.
There's this quote which I think applies here: if you want to bake an apple pie from scratch, you first need to invent the universe.
If you E&M questions are just node solving, linear algebra and difeq is all you need for E&M to solve "most" work. You do a lot of specialized versions of that in QM and as mentioned above the people doing the actual semiconductor design are so highly specialized that they are often not transferable to other problem domains and require fundamentally different approaches. Not sure any non-PHD study will really help one advance the field in a meaningful way. Study of QM i would say sufficiently enriches all physics verticals that if you are capable, it's worthy of individual pursuit, but also makes total sense to study as part of a curriculum taking place after intro E&M.
Quantum Tunneling in everyday life: https://www.discovermagazine.com/the-sciences/how-quantum-me...
Caltech had an elective course for freshman about how semiconductors worked up through flip-flops and registers. I took it. It involved QM and yes, tunnelling. So it's doable for mortals.
I read Charles Perzhold's Code, worked through parts of SICP, developed a bit of high level code software, have a very good knowledge of chemistry, lithographic processes (and QM, half forgotten by now). And yet it is not enough to get a good understanding of the modern computer - EE, compilers, OS de, networks, ... wiring the while thing together, et cetera.
I see the point in historical approaches, but it is quite time consuming. At the end, you will most likely attack problems at one to three levels in the "stack".
What would you consider to be an above average conceptual tool and skill set for the modern hacker?
Every time at this phase I'd suffer the existential horror the first time put an oscilloscope to the circuit -- the clock wasn't square! Signals would ring, and other signals which hadn't transitioned would sometimes bounce a bit. Setup and hold times could be pretty well estimated, but it was still an estimate. Then there were phantoms that might appear on the scope or real issues that would not show up on the scope because the probe lead was enough to make what was measured not the same as what was actually going on.
Your work sounds really interesing to me.
I am wondering about the reasons for these issues that you mentioned. Could you please mention them here ? It might serve as a nice pointer to do better hardware design debugging I believe(I have close to zero experience in this. Hence the interest).
Also, are there any formal systems that verify your TTL-level designs ?
Thank you.
A truly squarewave clock, or any rising/falling edge that happens in zero time would have infinite bandwidth, and no real circuit can have infinite bandwidth because of capacitance, inductance, and resistance. Even though the power rails of a TTL chip are 0V and 5V, when a fast transition happens, the signal can experience reflections because the impedance of the driver and the copper trace are different, and because the end of the copper trace isn't terminated with impedance which matches the trace. As a result, the edge takes finite time to transition from 0V to 5V, but the signal can actually exceed 5V because of a reflection. Likewise, falling signals can go below 0V.
Also, the signal at one end of a wire will not be the same as the signal at the other end of the wire. It isn't even just a simple time delayed version. Eventually they'll come to equilibrium if the signal is stable long enough.
You can read about transmission lines here: https://en.wikipedia.org/wiki/Transmission_line
OK, another defect. Imagine a TTL part with 8 buffers in it, say a 74ACT244. Say all the outputs are low, and at some moment seven of those inputs switch from low to high. The corresponding outputs must drive enough current to switch their loads from low to high as well. Each of those outputs draw current to charge their load from 0V to 5V, and all of the current flows through a single power pin and a single ground pin. Because of of non-zero resistance and inductance, the voltage seen by the transistors on the chip is shifted slightly from the voltage seen on the PCB. That can cause the output which isn't changing to sink/source current (depending on the direction of the change) causing its output to bounce a bit. Imagine having four people on a trampoline, with one standing still and three jumping at the same time. That "standing still" person will still bounce up and down because of the others causing their common ground reference to shift.
Another defect. A chip's spec sheet lists a bunch of requirements for proper operation and guarantees of the chip's behavior if the requirements are met. Say a flip flip says it has a 5ns setup time, that is, the data in to the flop must be held stable for 5ns before the rising edge of the clock arrives. If this requirement isn't met, the chip's behavior is unspecified (it might capture it, it might not, it might capture it but it might take an arbitrarily long time to appear on the output, or the output could even oscillate). During the design phase one adds up the worst case propagation times for all paths from point A to point B and makes sure there is at least 5ns to spare to guarantee the requirements. But in real life, a clock trace runs all over the board and has many loads, each presenting some amount of capacitance. Kind of like relativity, different chips will see the rising edge at different times. Looking at a given chip, the clock edge and data inputs are each transitioning from high to low or low to high over the course of a nanosecond (and often more). At what point on that slope is the signal really a "0" or a "1"? Sometimes those signals are clean transitions because of reflections, it might go from 0.7V before the clock edge, to -0.5V after the clock edge, to 2.2V (neither logical 0 nor 1), stay like that for a few ns, then move to 4.2V for a few ns, then 4.0V for a few ns, then 4.6V.
The most maddening is the fact you can't always trust what the oscilloscope tells you. The oscilloscope has finite bandwidth; 100MHz scopes were common in the 80s and early 90s when I was using them. The 200MHz scopes were a lot more expensive. You might think, hey my clock is only 25 MHz, 100 MHz is plenty ... but a fast signal edge contains harmonics that are a multiple of that 25 MHz base frequency, so the scope tends to act as a lowpass filter. The scope probe is typically more than a meter long, and there is a clip on the probe that must be attached to your circuit ground. That is a 2m loop of wire, and in the best case it would take a signal a few ns to travel the length of that wire, and any stray EM fields can induce signals on that probe that aren't in the circuit (though obviously the probe designers take pains to minimize such effects). When debugging and a signal looked unexpectedly weird, a common tactic to avoid sinking too much time chasing phantoms was to change the probe, change the channel, or simply waggle the lead wire around to test the sensitivity of the displayed waveform on stray capacitance and such.
Testbenches always had a few cans of refrigerant on hand. If you suspected a chip might be flaky, probe its output then spray it and see if the output is affected by the chip temperature.
The list goes on...
Also, Honestly, I thought reflections would be negligible when we are dealing with mA and 0-5V ranges. But your reply makes me think that there is more to it
Finally, thank you for your reply. I gonna come back to this answer in the future when I have a lab setup that is more than a solder and some screwdrivers :)
On RF designs it was not uncommon to find seemingly needless small valued components at certain probe points. The idea was these modeled the reactive load of a probe. When you needed to probe it you'd remove the components and attach your probe and the circuit see approximately the same load so you could have more faith that what you were seeing more closely matched what was happening when you weren't looking.
I have seen such small valued components, looked their values up and thought, "this is insane".
(I wish I could say I thought, "I must be dumb, someone must be much smarter than I am", but if I hadn't embodied a certain kind of hubris I would not work in software.)
This statement doesn't really make sense. If programmers spent the time to optimize everything instead of gluing a bunch of inefficient libraries together, software would cost even more than it does now. So that's even higher salaries because there is even more business competition for the same pool of available programmer hours in the workforce (and that doesn't even take into account the fact that you would wipe out 90% of the programming workforce if writing assembly is required).
Moore's law means that you can afford inefficient code, so it's taking money from programmers and keeping it in the businesses that would have originally had to pay for a hand-tuned piece of code.
But sure, if you want to talk performance - the fastest CPU this year, the Threadripper 3990X, is over 100x faster than the fastest CPU of 2005, the Athlon 64 FX-57. That's about 7-8 doublings, or pretty much spot on.
If you don't think so try and calculate a_{i+1} = rand_int() a_i mod 232 on a machine from today and one from 2005. Then do the same with a machine from 2005 and 1990.
At least, in theory.
It's not about knowing assembly or not. It's resources, time, cost, money, ROI.
Yes, once measurements were introduced after the Velvet Revolution, water consumption by households fell to half almost overnight.
I had to build a one-time export yesterday. Am I gonna spend a lot of time optimizing the speed of it? Or am I going to make it work and get the export to the client faster?
It would've wasted my time and the clients money if I optimized the queries. Sure, the export itself took longer. But overall, the task was done quicker.
If the client wanted this export to run on their server frequently, I would've spend the time making sure the export itself runs faster.
For exmaple, in your example of a one-time export it might also make sense to write code that does not meet all requirements and explicitly can not handle certain edge cases, if it's more effective to fix these cases manually than try to automate that.
> when technological progress or government policy increases the efficiency with which a resource is used (reducing the amount necessary for any one use), but the rate of consumption of that resource rises due to increasing demand
So from crap import * is pragmatic and practical. Short term at least.
That you know of.
1) In dynamic languages, it's not possible to detect whether a function is used or not in the general case. For example, consider string accesses on objects. If the compiler is not sophisticated enough to resolve the set of possible strings at compile time (or such analysis would unacceptably increase compile times), then you can't shake out unused methods on that object. [1]
2) For languages like C and C++, the compiler cannot tree shake because it only knows about a single file at a time (translation unit, to be precise). You would have to rely on link-time optimizations to effectively tree shake, but LTO is not well-supported by all toolchains.
Tree shaking also has a cost that I mentioned earlier -- it increases compile times. Both LTO and tree shaking in dynamic languages increase compile times superlinearly [citation needed] wrt. the size of your application. As other commenters have mentioned, it's better to avoid including unnecessary libraries in the first place.
There are no cost free abstractions, and that applies to tree shaking as well. https://www.youtube.com/watch?v=rHIkrotSwcc
[1] For the pedants: yes, I know resolving the possible set of values (stricter than "all possible values for that type") for a variable is undecidable in the general case.
You're right that people are already splitting apps into bundles, but that is usually done at the page level.
[1] You could probably avoid having to take a mutex after the first call to the function with self patching code, but that sounds incredibly ugly and could have other implications (self-modifying code could be detected as a virus; could be used as a gadget to exploit some other vulnerability).
The same can be done for a binary and it’s own code, but I wonder if it’s used as a signal in antivirus protections if done too often.
The closure js compiler is also pretty good if you prefer writing js.
If we only start using better languages in our applications we could improve performance quite a bit.
I’ve done assembler work, I’m perfectly competent at it. I would never try to build a website in anything low level like that. It’s optimizing for completely the wrong set of problems. The world has lots of network bandwidth, cpu cycles and volatile memory. You won’t find many situations where having a better performing website is worth sacrificing the savings in human labor you get from high level abstractions.
But we can't standardize because technology is improving so quickly. Any standard would be quickly obsolete.
If we ever standardize on one CPU, one screen size, one GPU, etc etc. Then we can make big gains by hyperfocusing on this.
If businesses demanded that everything be of optimal performance, developer salaries would most likely increase because that would increase demand for developer labour in the market without increasing its supply. And I know that many developers would be more than happy to do this (performance optimisation being one of these classic 'nerd sniping' tasks that really appeals to many programmers) but are simply not granted the time to.
And there is a reason that hardly anyone's boss is telling them to eek out every bit and clock cycle: they can't afford it, or at least don't want to pay to do that. So the "benefit" of doing this actually lands squarely on the business, if you want anywhere to look for wasted resources.
One can write assembly while knowing only a fraction of that stuff, but the compiler will probably outperform that kind of assembly, so there is little point aside from the fun of it.
https://www.penguinrandomhouse.com/books/645954/how-computer...
The book is still in writing stage thus not sure about the quality though but by looking at the table of contents it's looking very promising.
I tend to think that if more people understood how to program at this level, the weight of software and websites would be a lot less. I can't log in to my bank website without download 1 MB of crap. It's super easy to program using by importing * but if you can write in assembly you can really optimize. It's just not worth the effort these days. So the improvement of Moore's law (RIP) ends up going to programmers' salaries instead of to performance improvements. Kind of an interesting way to think about it.