Autosave: 2022-12-10 11:30:05

This commit is contained in:
thomasabishop 2022-12-10 11:30:05 +00:00
parent 70fbac3c2b
commit b32a80fc5e
44 changed files with 34 additions and 282 deletions

View file

@ -23,7 +23,7 @@ Connects local devices for example the harddisk to the CPU.
### External bus
Connects peripheral devices such as disks and printers to the [motherboard](/Hardware/Motherboard.md)
Connects peripheral devices such as disks and printers to the [motherboard](/Electronics_and_Hardware/Motherboard.md)
### Expansion bus
@ -31,7 +31,7 @@ Allows expansion boards to access the CPU and memory.
### Frontside bus
Main computer bus that determines data transfer rate speed and is the primary data transfer path between the CPU, RAM and other [motherboard](Motherboard.md) devices.
Main computer bus that determines data transfer rate speed and is the primary data transfer path between the CPU, RAM and other [motherboard](../Electronics_and_Hardware/Motherboard.md) devices.
### Backside bus

View file

@ -58,7 +58,7 @@ The CPU's [controller](/Hardware/Chipset_and_controllers.md). It takes the instr
Whilst modern CPUs and multithreading make it appear[] as though the CPU is capable of running multiple processes at once, access to the CPU is in fact sequential. The illusion of simultaneous computation is due to the fact the processor is so fast that we do not detect the sequential changes. For this to happen, the CPU needs to have a means of scheduling and sequencing processes. This is made possible through the system clock, hence when talking about the speed of the CPU we do so with reference to _clock speeds_ and the _clock cycle_.
The clock's circuitry is based on a quartz crystal system like that used in watches. At precisely timed intervals, the clock sends out pulses of electricity that cause bits to move from place to place within [logic gates](/Hardware/Logic_Gates/Logic_gates.md) or between logic gates and [registers](/Hardware/CPU/CPU_architecture.md#registers).
The clock's circuitry is based on a quartz crystal system like that used in watches. At precisely timed intervals, the clock sends out pulses of electricity that cause bits to move from place to place within [logic gates](/Hardware/Logic_Gates/Logic_gates.md) or between logic gates and [registers](/Computer_Architecture/CPU/CPU_architecture.md#registers).
Simple instructions such as add can often be executed in just one clock cycle, whilst complex operations such as divide will require a number of smaller steps, each using one cycle.
@ -68,7 +68,7 @@ A speed of 2GHz for example means two billion cycles per second. This would mean
## Processing cycles
Each "cycle" is the execution of a process that commences once the [kernel](/Operating_Systems/The_Kernel.md) hands control to the CPU. Each cycle follows a sequence of events known as [fetch, decode, and execute](/Hardware/CPU/Fetch_decode_execute.md).
Each "cycle" is the execution of a process that commences once the [kernel](/Operating_Systems/The_Kernel.md) hands control to the CPU. Each cycle follows a sequence of events known as [fetch, decode, and execute](/Computer_Architecture/CPU/Fetch_decode_execute.md).
## Electromagnetism: broader scientific context

View file

@ -4,41 +4,48 @@ categories:
tags: [CPU]
---
# Fetch, decode, execute, store
*Fetch, decode, execute* is the operating cycle of the CPU. We will run through how this works with reference to the [CPU architecture](/Hardware/CPU/CPU_architecture.md).
_Fetch, decode, execute_ is the operating cycle of the CPU. We will run through how this works with reference to the [CPU architecture](/Computer_Architecture/CPU/CPU_architecture.md).
## Fetch
### Overview
First, instructions and data are fetched from outside of the CPU chip (usually from the DRAM). In some cases, the data used by an instruction will be included with it. In other instance the instruction will reference the location where the data are held as an address.
### Specifics
* The Program Counter register needs to keep track and sequence the different instructions that the CPU will work on. The first place it will look for an instruction is at the DRAM address `0000`, equivalent to 0 in the Program Counter register: the starting point. This is address therefore copied to the Memory Address Register for future reference.
* This memory-storing event constitutes an instruction so it is copied to the Instruction Register.
* As the first instruction has been fetched, the system reaches the end of the first cycle. Thus the Program counter increments by 1 to log this.
* The next fetch cycle begins.
- The Program Counter register needs to keep track and sequence the different instructions that the CPU will work on. The first place it will look for an instruction is at the DRAM address `0000`, equivalent to 0 in the Program Counter register: the starting point. This is address therefore copied to the Memory Address Register for future reference.
- This memory-storing event constitutes an instruction so it is copied to the Instruction Register.
- As the first instruction has been fetched, the system reaches the end of the first cycle. Thus the Program counter increments by 1 to log this.
- The next fetch cycle begins.
## Decode
### Overview
Once the CPU has received the instruction, the CPU controller chip analyses it to determine which of its circuits should be used for processing.
### Specifics
### Overview
* Now that the instruction is fetched and stored in the RAM it needs to be decoded. It is therefore sent from the RAM to the Control Unit of the CPU. There are two parts to the instruction:
Once the CPU has received the instruction, the CPU controller chip analyses it to determine which of its circuits should be used for processing.
### Specifics
- Now that the instruction is fetched and stored in the RAM it needs to be decoded. It is therefore sent from the RAM to the Control Unit of the CPU. There are two parts to the instruction:
1. The operation code ("op code"): the command that the computer will carry out.
1. The operand: an address in RAM where the data will be read and written to as part of the execution
* The Control Unit converts the operation code and operand into an instruction that is fed to the next stage in the cycle: execution. For example, for an add function, `add` would be the op code and `address x` and `address y` would be the operands, thus the instruction would be: `add` the value in `address x` to the value in `address y`.
1. The operand: an address in RAM where the data will be read and written to as part of the execution
- The Control Unit converts the operation code and operand into an instruction that is fed to the next stage in the cycle: execution. For example, for an add function, `add` would be the op code and `address x` and `address y` would be the operands, thus the instruction would be: `add` the value in `address x` to the value in `address y`.
## Execute
## Execute
Now the command will be executed. The operand is copied to the Memory Address Register and then passed to the Memory Data Register and the command is carried out by the ALU.
The activities of ALU are covered in [CPU Architecture](/Hardware/CPU/CPU_architecture.md#arithmetic-logic-unit) and the notes on [Logic Gates](/Hardware/Logic_Gates/Logic_gates.md).
The activities of ALU are covered in [CPU Architecture](/Computer_Architecture/CPU/CPU_architecture.md#arithmetic-logic-unit) and the notes on [Logic Gates](/Hardware/Logic_Gates/Logic_gates.md).
## Store
### Overview
As well as telling the CPU what operation to perform, the instructions must specify where to store the result.
### Specifics
* Data is stored differently depending on the instruction.
* If the instruction is iterative (e.g. adding two numbers and then multiplying by another number), the instruction will tell the CPU to store the interim first value in the CPU's [registers](/Hardware/CPU/CPU_architecture.md#registers). As these are part of the CPU, the data can be retrieved more readily. If the value is not expected to be used again immediately, it goes to the DRAM or harddisk.
- Data is stored differently depending on the instruction.
- If the instruction is iterative (e.g. adding two numbers and then multiplying by another number), the instruction will tell the CPU to store the interim first value in the CPU's [registers](/Computer_Architecture/CPU/CPU_architecture.md#registers). As these are part of the CPU, the data can be retrieved more readily. If the value is not expected to be used again immediately, it goes to the DRAM or harddisk.

View file

@ -9,7 +9,7 @@ tags: [motherboard, chipset]
A **controller** is simply a circuit that controls a process. The **chipset** is a combination of controllers placed on the same piece of silicon.
The chipset manages the data flow between the different components that comprise the [motherboard](/Hardware/Motherboard.md): processor, [memory](/Hardware/Memory/Memory.md), [harddisk](/Operating_Systems/Disks/What_are_disks.md) and peripherals.
The chipset manages the data flow between the different components that comprise the [motherboard](/Electronics_and_Hardware/Motherboard.md): processor, [memory](/Hardware/Memory/Memory.md), [harddisk](/Operating_Systems/Disks/What_are_disks.md) and peripherals.
Buses run in and out of the chipset into these key motherboard components. The main chipset is a kind of junction that sits between the memory and CPU through which the [system bus](/Hardware/Bus.md#system-bus) passes.

View file

@ -25,7 +25,7 @@ When we think of memory we generally think of the _main_ memory: the 8GB or 16GB
### SRAM
SRAM (Static Random Access Memory) is also volatile memory but, in terms of the electronics, it is different in its implementation. In contrast to DRAM it doesn't use capacitors. As a result the transistors do not leak and therefore do not need to be refreshed, hence why SRAM is _static_ and DRAM is _dynamic_. It also uses multiple transistors per bit. This makes it faster than DRAM but more expensive. DRAM is at least ten times slower than SRAM. SRAM is used as [cache memory](/Hardware/Memory/Role_of_memory_in_computation.md#the-role-of-the-cache) on the [motherboard](/Hardware/Motherboard.md) of which there are two types: L1 (on the processor chip) and L2 (separate from the processor).
SRAM (Static Random Access Memory) is also volatile memory but, in terms of the electronics, it is different in its implementation. In contrast to DRAM it doesn't use capacitors. As a result the transistors do not leak and therefore do not need to be refreshed, hence why SRAM is _static_ and DRAM is _dynamic_. It also uses multiple transistors per bit. This makes it faster than DRAM but more expensive. DRAM is at least ten times slower than SRAM. SRAM is used as [cache memory](/Hardware/Memory/Role_of_memory_in_computation.md#the-role-of-the-cache) on the [motherboard](/Electronics_and_Hardware/Motherboard.md) of which there are two types: L1 (on the processor chip) and L2 (separate from the processor).
### Relative speeds

View file

@ -4,9 +4,7 @@ categories:
tags: [binary, binary-encoding]
---
# Image encoding
## Binary encoding of colours
# Binary encoding of colours
The approach to encoding binary representations of colour is very similar to the approach we explored when looking at the encoding of [alphanumeric values](/Hardware/Binary/Text_encoding.md).

View file

@ -4,10 +4,11 @@ categories:
- Hardware
tags: [motherboard]
---
# Motherboard
<img src="../img/motherboard-pi.jpg" width="400px"/>
The motherboard is the foundation of a computer. It allocates power and allows communication to and between the [CPU](./CPU/Von_Neumann_architecture.md), [RAM](./Memory/Basics.md), [harddisk](/Operating_Systems/Disks.md) and all other hardware components.
The motherboard is the foundation of a computer. It allocates power and allows communication to and between the [CPU](./../Computer_Architecture/CPU/Von_Neumann_architecture.md), [RAM](../Hardware/Memory/Basics.md), [harddisk](/Operating_Systems/Disks.md) and all other hardware components.
It is a printed circuit board and is always the largest board within the computer chassis.
It is a printed circuit board and is always the largest board within the computer chassis.

View file

@ -10,7 +10,7 @@ tags:
# Relation between the kernel and CPU
It can be confusing to understand how the kernel and CPU interact with one another. Whilst it is true to say the kernel mediates between the hardware and user processes, this led me to think that the kernel was somehow 'over and above' the actions of the CPU. This is wrong and if you think about it, how could this be since any process, kernel included, requires the processor? The kernel is executed by and loaded into the CPU just like any other instruction in the [fetch, decode, execute cycle](/Hardware/CPU/Fetch_decode_execute.md) of the CPU.
It can be confusing to understand how the kernel and CPU interact with one another. Whilst it is true to say the kernel mediates between the hardware and user processes, this led me to think that the kernel was somehow 'over and above' the actions of the CPU. This is wrong and if you think about it, how could this be since any process, kernel included, requires the processor? The kernel is executed by and loaded into the CPU just like any other instruction in the [fetch, decode, execute cycle](/Computer_Architecture/CPU/Fetch_decode_execute.md) of the CPU.
However as a process, the kernel is the 'first amongst equals' given that it is the core embodiment of the operating system. At boot time, the kernel is injected into memory and at this point the CPU _looks to this address_ in memory in order to source its first instruction. That's how the kernel gets going. It is the first instruction that the CPU fetches and this is what allows the kernel to play its mediatory role. However most of the fetch, decode, execute cycles of the CPU take place independently of the kernel.

View file

@ -1,254 +0,0 @@
---
title: Creating a GraphQL server
categories:
- Databases
tags: [graphql]
---
# Creating a GraphQL server
> We will use Node.js to create a basic GraphQL server that will serve data from a product database.
Our server will allow us to add products to a database through a mutatation and to query the products that we have added. We will use a JS object instead of a real database.
## Create a basic Express server
First we create a basic server in Node using Express:
```js
import express from "express";
app.get("/", (req, res) => {
res.send("Graph QL test project");
});
app.listen(8080, () =>
console.log("Running server on port localhost:8080/graphql")
);
```
## Add GraphQL as middlewear
Next we introduce GraphQL as a piece of Node.js [middlewear](/Programming_Languages/Node/Architecture/Middleware.md), with the `app.use()` method.
```js
import { graphqlHTTP } from "express-graphql";
app.use(
"/graphql",
graphqlHTTP({
schema: schema,
rootValue: resolvers,
graphiql: true,
})
);
```
- `schema` is a reference to our GraphQL schema - the structure of the fields that define our server. This is not yet defined.
- `rootValue` is a reference to our resolvers. This is not yet defined.
- `graphiql` is the GUI tool that will be served from the GraphQL endpoint at `localhost:8080/graphql`. This tool enables us to interrogate our data using the defined schema and see what data we would get back from frontend queries.
## Resolvers
We will specify our resolvers in a dedicated resolver file. In GraphQL you need to define resolvers for both your queries and your mutations.
To achieve this we will have a dummy object as the database containing our products and a class working as a generator function that will create a product object with certain properties, individuated by an id. We will invoke this class to create new products for the database and to retrieve existing products from the database.
First we create the product class and the database object:
```js
// resolvers.js
const productDb = {};
class Product {
constructor(id, { name, description, price, soldout, stores }) {
this.id = id;
this.name = name;
this.description = description;
this.price = price;
this.soldout = soldout;
this.stores = stores;
}
}
```
Next we define a resolver for read operations. This will receive a product id and return the corresponding product back from the database as an instance of `Product`.
```js
// resolvers.js
const resolvers = {
getProducts: ({ id }) => {
return new Product(id, productDb[id]);
},
};
```
Next we declare a resolver that will handle our mutation: adding new products to the database.
> Mutations in GraphQL are the equivalent of `POST`, `PUT`, and `DELETE` in REST APIs. In other words, they are the means by which we update the data that the GraphQL Server exposes.
```js
// resolvers.js
const resolvers = {
getProducts: ({ id }) => {
return new Product(id, productDb[id]);
},
createProduct: ({ input }) => {
let id = guid; // imagine a hash function here
productDatabase[id] = input;
return new Product(id, input);
},
};
```
## Schema
This handles the backend mechanics of reading from and writing to the database, but we need still need to integrate it with the GraphQL middlewear. We do this through the GraphQL server's schema file.
The GraphQL Schema, defined on the backend, describes the shape of queries that can be run against the GraphQL Server. A schema is a series of fields matched to a type specification. Writing a schema is just like defining a type or interface in TypeScript or a schema in Mongoose.
### Define `Product` type
First we will define a schema entry for products:
```js
// schema.js
import { buildSchema } from "graphql";
const schema = buildSchema(`
type Product {
id: ID
name: String
description: String
price: Float
soldout: Boolean
stores: [Store]!
}
type Store {
store: String
}
`);
```
> Note that here we define a **custom** `Store` type that integrates with the the `Product` type as an array of stores. This is a required field, indicated by the `!`. Also the `ID` type is special ...
// TODO: Explain why the ID type is in caps. Is it the equivalent of the primary key?
### Define `Query` method
So far we have established the types necessary to service our `getProduct` resolver but we have not provided a declared means of querying. We do this by declaring a `Query` type that will invoke the `getProduct` resolver we defined earlier. Now the server knows that when a `Query` is run, it must use that resolver:
```js
const schema = buildSchema(`
...
type Query {
getProducts(id: ID)
}
`);
```
### Define `Mutation`
So far we have defined the fields necessary to query the GraphQL server using the `getProduct` resolver but we have not yet provided a way to mutate the data by adding new products. We need to integrate our `createProduct` resolver.
We do this by defining a `Mutation` type that references the `createProduct` resolver. And we type its paramter and return value:
```js
const schema = buildSchema(`
...
type Mutation {
createProduct(input: ProductInput): Product
}
input ProductInput {
id: ID
name: String
description: String
price: Float
solout: Boolean
stores: [StoreInput]!
}
type StoreInput {
store: String
}
`);
```
> Note that the `input` parameter to the mutation and the `input` keyword are closely coupled. Note also that although `ProductInput` / `Product` and `Store` / `StoreInput` are identical in terms of their shape, we must still create dedicated new types. We cannot mix the types from the different resolvers.
## Using the server
Our server is now complete and will allow us to send and receive data of the following shape:
```json
{
"id": 1234,
"name": "Product A",
"description": "This is Product A",
"price": 34.99,
"soldout": false,
"stores": [
{
"store": "London"
},
{
"store": "Sheffield"
},
{
"store": "Lincoln"
}
]
}
```
We will now switch to the client-side and see how we can go about adding and querying products.
### Adding new products through a mutation
We can invoke our mutation resolver by sending the following query to the server:
```graphql
mutation {
createProduct(
input: {
name: "Widget4"
description: "Lorem ipsum"
price: 39.99
soldout: false
stores: [{ store: "London" }]
}
) {
price
name
soldout
}
}
```
This is represented in GraphiQL as follows:
![](/img/graphql3.png)
We should always return something, even if we are applying  mutation, hence we add the properties at the bottom as the ones we want to return.
### Returning a product through a query
```graphql
```
// Add new image of this working in GraphiQL
// TODO: Explain input types (https://graphql.org/graphql-js/mutations-and-input-types/)
// TODO: Explain enums